非阻塞方式程序設計介紹
非阻塞方式的操作與阻塞方式的操作最大的不同點是函數的調用立刻返回,不管數據是否成功讀取或者成功寫入。使用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;
}