套接字Select模型是比较常用的一种I/O模型,利用该模型使得Windows Sockets应用程序可以在同一时间内
管理和控制多个套接字,该模型的核心就是select()函数----调用select()函数检查当前多个套接字的状态----是否可读,可写,有异常。。。。。根据该函数的返回值,判断套接字的可读可写性,然后调用相应的Windows Sockets API函数完成数据的发送和接收等操作。。。。【阻塞模式】 套接字执行I/O操作时,如果执行操作的条件没有得到满足,线程会被阻塞在该调用的函数上,
程序不得不处于等待状态,该调用函数什么时候返回,不得而知;【非阻塞模式】 套接字执行I/O操作时,无论在何种情况下,调用函数都会立即返回,软件设计人员需要编写
更多的代码,对函数返回的错误码(nErrCode)进行处理(GetLastError()),有时候在应用程序中 往往需要在一个循环体内反复调用该函数,直到该函数返回成功结果为止,这显然不是好办法。 【select()函数】int select(int nfds, fd_set FAR* readfds, fd_set FAR* writefds, fd_set FAR* exceptfds const struct timeval FAR* timeout);【0】nfds 可被忽略,与Berkeley套接字应用程序兼容
【1】readfds 具有可读性套接字集合的指针;【2】writefds 具有可写性套接字集合的指针;【3】exceptfds 检查错误套接字集合的指针;【4】timeout 设置该select()函数等待时间 #define FD_SETSIZE 64typedef struct fd_set{ u_int fd_count; SOCKET fd_addry[FD_SETSIZE];}fd_set;struct timeval
{ long tv_sec; long tv_usec;};timeout == NULL; 表示无限等待,直到条件符合返回
timeout == 0; 立即返回 timeout == **** 表示等待****时间之后返回FD_CLR(s, *set) 从set集合中删除s套接字
FD_ISSET(s, *set) 检查s是否是set集合中的一名成员FD_SET(s, *set) 将套接字s加入到set集合中FD_ZERO(*set) 将set集合初始化为空集合 常用代码结构SOCKET listenSocket;
FD_SET allfd;FD_SET readfd;FD_SET writefd;int reVal;FD_ZERO(&allfd);
FD_SET(listenSocket, &allfd);while(1)
{ FD_ZERO(readfd); FD_ZERO(writefd); readfd = allfd; writefd = allfd;reVal = select(0, &readfd, &writefd, NULL, NULL);
if(reVal == SOCKET_ERROR) { // 错误处理 } if(reVal > 0) { for(int i = 0; i < allfd.fd_count; i++) { SOCKET sTmp = allset.fd_array[i]; if(FD_ISSET(sTmp, &readfd)) // 可读性 有数据可读 或者 有连接发起 { if(sTmp == listenSocket) // 因为listenSocket 不断监听指定端口是否有连接发起,现在有链接发起 { // 建立新的连接 SOCKET NewAcceptSocket = accept(listenSocket, NULL, NULL); // .......... } else { // 有数据可以接受 RecvData() // .......... } }if(FD_ISSET(sTmp, &writefd))
{ // SendData() // ........... } } }}