当前位置: 首页 > 编程技术, 网络技术 > 正文

Winsocket编程一般步骤-服务端编程

Socket编程是网络编程的重要组成部分,编写简单的服务端程的程序的一般的步骤如下

第一步:包含WinSocket的头文件和动态链接库(DLL)

#include <Winsock2.h>
#include <windows.h>
#pragma comment(lib,"ws2_32")

第二步:初始化WSAStartup 在MSDN中WSAStarup的原型如下:

int WSAStartup(
  __in   WORD wVersionRequested,
  __out  LPWSADATA lpWSAData
);


其中的第一个参数是版本,第二个参数是一个指向WSADATA结构体的指针,代码如下:

WORD Version = MAKEWORD(2,2);  //通过MAKEWORD来设定版本,高版本和低版本都为2,也就是限定了版本必须为2
WSADATA wsadata ;                       //结构体的一个成员 wsadata

//初始化并判断是不是成功,如果成功的话返回的是0,不成功的话返回的值为非0,那么就要使用WSAleanup()函数了

if(WSAStartup(Version,&wsadata)){
cout<<"WSAStartup Error!"<<endl;
WSACleanup();
}

第三部,初始化一个Socket,

在MSDN中socket的原型如下

SOCKET WSAAPI socket(
  __in  int af,
  __in  int type,
  __in  int protocol
);

其中第一个参数为网络层协议类型,第二个参数为socket类型,第三个参数为传输层的协议类型,代码如下:

//第一个参数多数时候为AF_INET,第二个参数可以为SOCK_STREAM适用于可信连接,也就是tcp链接,或者为SOCK_DGRAM,适用于UDP协议
第三个参数为传输层协议,如果第二个参数为SOCK_STREAM,这里就为IPPROTO_TCP,如果是SOCK_DGRAM,这里就为IPPROTO_UDP

SOCKET ServerSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(ServerSocket ==INVALID_SOCKET){
	cout<<"Socket Fail"<<endl;
}

第四步:bind
在MSDN中bind的定义如下:

int bind(
  __in  SOCKET s,
  __in  const struct sockaddr* name,
  __in  int namelen
);

第一个参数一个已经初始化的socket,第一个参数为执行sockaddr或者是sockaddr_in的结构体的起始地址,

第三个参数为结构体的大小,代码如下:

sockaddr_in  ServerAddr;//定义一个结构体成员,这里使用的是sockaddr_in结构体
ServerAddr.sin_family=AF_INET;//初始化成员的sin_family为AF_INET
ServerAddr.sin_addr.S_un.S_addr=INADDR_ANY;//允许任意的IP地址进行连接
ServerAddr.sin_port=htons(2012);//侦听端口为2012,这里使用了htons函数
//这里需要说明的是需要对第二个参数进行强制类型转换,(LPSOCKADDR)&ServerAddr,并且判断是不是bind成功,成功后返回的是为0
if(bind(ServerSocket,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr))){
	cout<<"bind Fail"<<endl;
}

第五步:侦听
在MSDN中listen的原型如下:

int listen(
  __in  SOCKET s,
  __in  int backlog
);

依然第一个参数为初始化了的socket,第二个参数为最大允许的连接数,代码如下:

//这里依然使用的是上面的socket:ServerSocket
if(listen(ServerSocket,5)){
	cout<<"listen Fail"<<endl;
}

第六步:accept
在MSDN中原型如下:

SOCKET accept(
  __in     SOCKET s,
  __out    struct sockaddr* addr,
  __inout  int* addrlen
);

第一个参数一个新的客户端的Socket,这里需要定义一个,第二个参数依然为执行sockaddr或者是sockaddr_in的结构体的首地址,第三个参数为长度,这里accept负责对新定义的socket进行初始化,如果成功accept返回的一个可用的sokcet。
代码如下:

sockaddr_in Clientaddr;//定义一个结构体成员
SOCKET ClientSocket;//定义一个socket用于接收accept的返回值
int lAddrlen=sizeof(Clientaddr);//获取结构体的长度
while(TRUE){//因为要一直的侦听,所以这里使用无限循环
ClientSocket=accept(ServerSocket,(LPSOCKADDR)&Clientaddr,&lAddrlen);
//与上面类似,需要强制转换,第一个参数为已经初始化的socket
if(ClientSocket==INVALID_SOCKET){
cout<<"accept Fail"<<endl;
}
else{
cout<<"接受到一个信息"<<endl;
}

第七步:如果accept成功,recv消息
在MSDN中recv原型如下:

int recv(
  __in   SOCKET s,
  __out  char* buf,
  __in   int len,
  __in   int flags
);

第一个参数为accept返回的socket,第二个参数为输出接收的消息的一个指针,第三个为消息的长度,第四个为标志,设定接收数据的方式,代码如下:

char  RecvMessage[1024];
 //判断是不是成功接收,成功接收返回的是接收的数据的长度,
if(recv(ClientSocket,RecvMessage,1024,0){
cout<<"recv Message Fail"<<endl;
}

第八步:(可选):回复客户端消息 send
send在MSDN中的代码如下:

int send(
  __in  SOCKET s,
  __in  const char* buf,
  __in  int len,
  __in  int flags
);

第一个参数为accept返回的socket,第二个参数为内容的开始地址,第三个为长度,第四个为发送的方式,代码如下:

char * Message ="HellO Client!";
   //判断是不是成功发送,成功发送返回的是发送的字节数,
if(send(ClientSocket,Message,strlen(Message),0){
cout<<"send Message Fail"<<endl;
}

第九步:完成后,关闭客户端与服务端的socket:

closesocket(ClientSocket);
}//上面while的结束部分

第十步:“清理”现场:

closesocket(ServerSocket);
WSACleanup();
return 0;

总结下,代码如下:

#include <iostream>
#include <Winsock.h>
#pragma comment(lib,"ws2_32")
using namespace std;
int main(int argc,char argv[])
{
WORD Version = MAKEWORD(2,2);
WSADATA wsadata ;

if(WSAStartup(Version,&wsadata)){
cout<<"WSAStartup Error!"<<endl;
WSACleanup();
}
SOCKET ServerSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(ServerSocket ==INVALID_SOCKET){
cout<<"Socket Fail"<<endl;

}

sockaddr_in ServerAddr;
ServerAddr.sin_family=AF_INET;
ServerAddr.sin_addr.S_un.S_addr=INADDR_ANY;
ServerAddr.sin_port=htons(2012);
if(bind(ServerSocket,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr))){
cout<<"bind Fail"<<endl;

}
if(listen(ServerSocket,5)){
cout<<"listen Fail"<<endl;

}

sockaddr_in Clientaddr;
SOCKET ClientSocket;
int lAddrlen=sizeof(Clientaddr);
while(TRUE){

ClientSocket=accept(ServerSocket,(LPSOCKADDR)&Clientaddr,&lAddrlen);
if(ClientSocket==INVALID_SOCKET){
cout<<"accept Fail"<<endl;
}
else{
cout<<"接受到一个信息"<<endl;
}

char RecvMessage[1024];
if(recv(ClientSocket,RecvMessage,1024,0)<0){
cout<<"recv Message Fail"<<endl;

}
char * Message ="HellO Client!";
if(send(ClientSocket,Message,strlen(Message),0)<0){
cout<<"send Message Fail"<<endl;
}
closesocket(ClientSocket);
}
closesocket(ServerSocket);
WSACleanup();
return 0;

}


本文固定链接: http://kuaile.in/archives/311 | 蒲公英的博客

该日志由 蒲公英 于2012年01月31日发表在 编程技术, 网络技术 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: Winsocket编程一般步骤-服务端编程 | 蒲公英的博客
关键字:

Winsocket编程一般步骤-服务端编程:等您坐沙发呢!

发表评论


You must enable javascript to see captcha here!

快捷键:Ctrl+Enter