要是用Socket实现基本的通信,主要分以下几个步骤。
1.初始化
函数原型:int WSAStartup( WORD wVersionRequired, LPWSADATA lpWSAData );
参数1:版本选择
参数2:设置一个指向WSADATA数据类型的指针
返回值为0时,表示该函数执行成功。
Startup = WSAStartup(MAKEWORD(2, 2), &wsadata); if (Startup != 0) { printf("Failed to WSAStartup !\n"); break; }
2.申请Socket
函数原型:int socket( int af, int type, int protocol);
参数1:选择地址族(如:AF_INET为ipv4,AF_INET6为ipv6)
参数2:选择套接字类型
参数3:选择协议
返回值:返回套接字描述符
SrvSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == SrvSocket) { printf("Socket invoke failed !\n"); break; }
3.设置Socket地址及端口
需声明一个SOCKADDR_IN类型的结构体,具体示例如下
SOCKADDR_IN LocalAddr; LocalAddr.sin_family = AF_INET; //地址族,如AF_INET,带标TCP/IP地址族 LocalAddr.sin_addr.S_un.S_addr = 0; //存储IP地址 LocalAddr.sin_port = htons(26822); //存储端口号(htons将整型变量从主机字节顺序转变成网络字节顺序) memset(LocalAddr.sin_zero, 0x0, sizeof(LocalAddr.sin_zero)); //sin_zero是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节 //用来将sockaddr_in结构填充到与struct sockaddr同样的长度,可以用memset()函数将其置为零。
4.绑定IP地址
函数原型:int bind( SOCKET s, const sockaddr *addr, int namelen );
参数1:套接字描述符
参数2:指向要分配给绑定套接字的本地地址的sockaddr结构的指针
参数3:名称参数所指向的值的长度(以字节为单位)
SrvBind = bind(SrvSocket, (SOCKADDR*)&LocalAddr, sizeof(SOCKADDR_IN)); if (0 != SrvBind) { printf("Failed to bind !\n"); printf("Bind Error Code:%u", WSAGetLastError()); break; }
5.监听Socket
函数原型:int listen( SOCKET s, int backlog );
参数1:套接字描述符
参数2:挂起连接队列的最大长度。如果将backlog设置为SOMAXCONN,则负责套接字s的基础服务提供商会将backlog设置为最大合理值。没有标准条款来获取实际积压值。
SrvListen = listen(SrvSocket, 5); if (0 != SrvListen) { printf("Failed to listen !\n"); break; }
6.接受链接
函数原型:SOCKET WSAAPI accept( SOCKET s, sockaddr *addr, int *addrlen );
参数1:标示一个已处于监听状态下的套接字
参数2:通信层已知的指向接收连接实体地址的缓冲区的可选指针。addr参数的确切格式由创建sockaddr结构的套接字时建立的地址族确定 。
参数3:指向整数的可选指针,该整数包含addr参数指向的结构的长度。
AddrLen = sizeof(Clientaddr); AcceptSocket = accept(SrvSocket, (SOCKADDR*)&Clientaddr, &AddrLen); if (INVALID_SOCKET == AcceptSocket) { printf("Accept error !\n"); break; }