非阻塞方式程序设计介绍
非阻塞方式的操作与阻塞方式的操作最大的不同点是函数的调用立刻返回,不管数据是否成功读取或者成功写入。使用fcntl()将套接字文件描述符按照如下的代码进行设置后,可以进行非阻塞的编程:
fcntl(s, F_SETFL, O_NONBLOCK);
其中的s是套接字文件描述符,使用F_SETFL命令将套接字s设置为非阻塞方式后,再进行读写操作就可以马上返回了。
非阻塞程序设计的例子
函数accept()可以使用非阻塞的方式轮询等待客户端的到来,在之前要设置NON_BLOCK方式。下面的代码使用了轮询的方式使用accept()和recv()函数,当客户端发送“HELLO”字符串时,发送“OK”响应给客户端并关闭客户端;当客户端发送“SHUTDOWN”字符串给服务器时,服务器发送“BYE”的客户端,并关闭客户端,然后退出程序。
#define PORT 9999
#define BACKLOG 4
int main(int argc, char *argv[])
{
? ? struct sockaddr_in local,client;
? ? int len;
? ? int s_s? = -1,s_c= -1;
? ? /* 初始化地址结构 */
? ? bzero(&local, sizeof(local));? ? ? /* 清0 */
? ? bzero(&client, sizeof(client));? ? /* 清0 */
? ? local.sin_family = AF_INET;
? ? local.sin_port = htons(PORT);
? ? local.sin_addr.s_addr = htonl(-1);
? ? /*建立套接字描述符*/
? ? s_s = socket(AF_INET, SOCK_STREAM, 0);
? ? /*设置非阻塞方式*/
? ? fcntl(s_s,F_SETFL, O_NONBLOCK);
? ? /*侦听*/
? ? listen(s_s, BACKLOG);
? ? for(;;)
? ? {
? ? ? ? /*轮询接收客户端*/
? ? ? ? while(s_c < 0){/*等待客户端到来*/
? ? ? ? ? ? s_c =accept(s_s, (struct sockaddr*)&client, &len);
? ? ? ? }
? ? ? ? /*轮询接收,当接收到数据的时候退出while循环*/
? ? ? ? while(recv(s_c, buffer, 1024)<=0)
? ? ? ? ? ? ;
? ? ? ? /* 接收到客户端的数据 */
? ? ? ? if(strcmp(buffer, "HELLO")==0){/*判断是否为HELLO字符串*/
? ? ? ? ? ? send(s, "OK", 3, 0);/*发送响应*/
? ? ? ? ? ? close(s_c);? ? ? ? /*关闭连接*/
? ? ? ? ? ? continue;? ? ? ? ? /*继续等待客户端连接*/
? ? ? ? }
? ? ? ? if(strcmp(buffer, "SHUTDOWN")==0){/*判断是否为SHUTDOWN字符串*/
? ? ? ? ? ? send(s, "BYE", 3, 0);? /*发送BYE字符串*/
? ? ? ? ? ? close(s_c);? ? ? ? ? ? /*关闭客户端连接*/
? ? ? ? ? ? break;? ? ? ? ? ? ? ? ? /*退出主循环*/
? ? ? ? }
? ? }
? ? close(s_s);
? ? return 0;
}