client_sockselect的基本使用 函数原型: int select( __in int nfds, __inout fd_set *readfds, __inout fd_set *writefds, __inout fd_set *exceptfds, __in const struct timeval *timeout ); 参数说明: nfds: 与Berkeley 套接字兼容,没有什么作用,忽略 readfds: 检查设置的套接字是否可以读,可以忽略 writefds:检查设置的套接字是否可以写,可以忽略 exceptfds: 检查套接字的错timeout:select等待的时间。NULL:阻塞状态;初始为{0,0}时,立即返回 返回值:返回fd_set中的套接字句柄数;0:等待时间超时; SOCKET_ERROR发生错误,使用WSAGetLastError获得具体的错误代码。 操作fd_set的宏: FD_CLR(s, *set) 从set中移除 FD_ISSET(s, *set) 如果s是set的成员返回非0,否则返回0 FD_SET(s, *set) 把 s添加到set中 FD_ZERO(*set) 初始化set为null
使用select使用的几个步骤 1. 使用FD_ZERO对fd_set结构清空 2. 添加套接字句柄到fd_set中,使用FD_SET宏 3. 调用select 4. 使用FD_ISSET判断是哪个套接字 5. 进行读写操作,然后返回步骤1
下面是一个简单例子
#include <winsock2.h> #include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
#define LISTEN_PORT 5080 #define RECV_BUFF_SIZE 512
int main(void) { WSADATA wsadata; int ret; SOCKET listen_sock; SOCKET client_sock; SOCKADDR_IN listen_addr; SOCKADDR_IN in_addr; int in_add_len = sizeof(in_addr); fd_set fdread; char recv_buff[RECV_BUFF_SIZE];
ret = WSAStartup(MAKEWORD(2,2), &wsadata); if(0 != ret) { printf("WSAStartup error:%d.\n", WSAGetLastError()); return -1; }
listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(INVALID_SOCKET == listen_sock) { printf("socket error:%d.\n", WSAGetLastError()); goto rettag1; }
listen_addr.sin_family = AF_INET; listen_addr.sin_addr.s_addr = htonl(INADDR_ANY); listen_addr.sin_port = htons(LISTEN_PORT);
ret = bind(listen_sock, (SOCKADDR*)&listen_addr, sizeof(listen_addr)); if(SOCKET_ERROR == ret) { printf("bind error:%d.\n", WSAGetLastError()); goto rettag2; }
ret = listen(listen_sock, 5); if(SOCKET_ERROR == ret) { printf("listen error:%d.\n", WSAGetLastError()); goto rettag2; }
client_sock = accept(listen_sock, (SOCKADDR*)&in_addr, &in_add_len); if(INVALID_SOCKET == client_sock) { printf("accept error:%d.\n", WSAGetLastError()); goto rettag2; } else { printf("accept client:%s:%d.\n", inet_ntoa(in_addr.sin_addr), in_addr.sin_port); }
while(1) { FD_ZERO(&fdread); FD_SET(client_sock, &fdread); ret = select(0, &fdread, NULL, NULL, NULL); if(SOCKET_ERROR == ret) { printf("select error:%d.\n", WSAGetLastError()); } if(ret > 0) { if(FD_ISSET(client_sock, &fdread)) { ret = recv(client_sock, recv_buff, RECV_BUFF_SIZE, 0); if(SOCKET_ERROR == ret) { printf("recv error:%d.\n", WSAGetLastError()); } else if(0 == ret) { printf("recv, socket closed.\n"); break; } else { printf("receive data:\n%s\n", recv_buff); } } } } closesocket(client_sock ); rettag2: ret = closesocket(listen_sock); if(SOCKET_ERROR == ret) { printf("closesocket error:%d.\n", WSAGetLastError()); }
rettag1: ret = WSACleanup(); if(0 != ret) { printf("WSACleanup error:%d.\n", WSAGetLastError()); return -1; }
return 0; }
|