资源预览内容
第1页 / 共5页
第2页 / 共5页
第3页 / 共5页
第4页 / 共5页
第5页 / 共5页
亲,该文档总共5页全部预览完了,如果喜欢就下载吧!
资源描述
Socket 通信接口的模式选择选择(select)模型是 Winsock 中最常见的 I/O 模型。核心便是利用 select 函数,实现 对 I/O 的管理!利用 select 函数来判断某 Socket 上是否有数据可读,或者能否向一个 套接字写入数据,防止程序在 Socket 处于阻塞模式中时,在一次 I/O 调用(如 send 或 recv、accept 等)过程中,被迫进入“锁定”状态;同时防止在套接字处于非阻塞模式中 时,产生 WSAEWOULDBLOCK 错误。select 函数原型:int select(int nfds, /传入参数,忽略fd_set FAR * readfds, /检查可读性fd_set FAR * writefds, /检查可写性fd_set FAR * exceptfds, /例外数据const struct timeval FAR * timeout /本次 select 调用最长的等待时间);函数返回值,select()函数调用后,返回处于就绪状态并且已经包含在 fd_set 结构中的套 接口描述符,也就是说,它要修改集合,删除那些不能进行指定操作的套接口。但如果超 时则返回 0;如果发生错误,则返回 SOCKET_ERROR,应用程序可通过 WSAGetLastError() 获取错误代码。 其中 fd_set 是一个结构类型说明符,代表着一系列特定套接口的集合,它的定义如下:typedef struct fd_set u_int fd_count; /* how many are SET? */SOCKET fd_array FD_SETSIZE; /* an array of SOCKETs */ fd_set;timeval 是一个结构类型,它的定义如下:struct timeval long tv_sec; /* seconds */long tv_usec; /* and microseconds */ ;若将超时值设置为(0 , 0),表明 select 会立即返回,出于对性能方面的考虑,应避免 这样的设置。以下为测试 select()函数的程序,一个服务器端两个客户端下面是服务器端程序:#define FD_SETSIZE 500 #include #pragma comment ( lib, “ws2_32“ ) #include int main() printf( “服务器端程序.n“ );/-加载-WSADATA wsaData;if ( WSAStartup( MAKEWORD( 2 ,2 ),return 1 ;elseprintf( “加载成功n“ );/-创建流式套接字-SOCKET s= socket( AF_INET, SOCK_STREAM, 0 );if ( s= INVALID_SOCKET)printf( “socket() Failed,Error=【%d】n“ , WSAGetLastError();return 1 ;elseprintf( “已创建监听套接口:【%d】n“ , s);/将套接口 s 置于”非阻塞模式“u_long u1= 1 ;ioctlsocket( s, FIONBIO,( u_long*)/-绑定本地地址-struct sockaddr_in Sadd;Sadd.sin_family= AF_INET;Sadd.sin_port= htons( 5555 );Sadd.sin_addr.S_un.S_addr= inet_addr( “192.168.31.1“ );if ( bind( s,( sockaddr*)return 1 ;elseprintf( “绑定成功,本地 IP 地址:【%s】,端口号:【%d】n“ , inet_ntoa( Sadd.sin_addr), ntohs( Sadd.sin_port);/-进入监听状态-if ( listen( s, 3 )= SOCKET_ERROR)printf( “listen Failed,Error=【%d】n“ , WSAGetLastError();return 1 ;elseprintf( “进入监听状态n“ );/-select-/准备工作int x= 1 ;timeval tv;tv.tv_sec= 20 ;tv.tv_usec= 0 ;fd_set socket_jh01;FD_ZERO(FD_SET( s,fd_set socket_jh02;FD_ZERO(while ( TRUE )socket_jh02= socket_jh01;int sock_sum= select( 0 ,/-情况一 成功if ( sock_sum 0 )for ( int i= 0 ;i 0 )printf( “接收到来至【%d】的数据:%sn“ , socket_jh02.fd_array i, cbuf);int isend;char Sbuf= “Hello client!I am server“ ;isend= send( socket_jh02.fd_array i, Sbuf, sizeof ( Sbuf), 0 );if ( isend= SOCKET_ERROR)printf( “send() Failed,Error=【%d】n“ , WSAGetLastError();break ;else if ( isend= 0 )printf( “消息发送失败!n“ );break ;elseprintf( “给客户【%d】信息已发送,信息长度%d 字节nn“ , socket_jh02.fd_array i, isend);elseprintf( “客户端【%d】不再发送数据,正常关闭连接,为客户 端连接创建的套接口将关闭!n“ , socket_jh02.fd_array i);closesocket( socket_jh02.fd_array i);FD_CLR( socket_jh02.fd_array i, /end for /end sock_sum/-情况二 超时else if ( sock_sum= 0 )printf( “第【%d】次超时n“ , x);if ( x 3 )x+;continue ;elseprintf( “超过等待限制,退出程序n“ );break ;/-情况三 失败elseprintf( “select() Failed,Error=【%d】n“ , WSAGetLastError();break ; /while endclosesocket( s);printf( “退出“ );WSACleanup();return 0 ; 在 linux 系统下,socket 通信的选择模式是根据具体的网络应用而定的。对于服务器来说, socket 的 select 模式无疑对系统效能产生了很大的影响,极其影响系统的效率。因此对于 服务器来讲,像 ngnix 这种方向代理服务器来说,采用 epoll 模型的网络 IO 模式无疑是最 好的选择。而对于我们平时的一般应用,没有太大的区别。
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号