select()
和poll()
的大多数示例的工作方式与此类似:
int activity = select(FD_SETSIZE, &readfds , NULL , NULL , NULL);
//...
for (i = 0; i < max_clients; i++){
int sd = client_socket[i];
if (FD_ISSET(sd , &readfds)){
int len = read(sd , buffer, 1024);
if (len == 0){
// disconnect
}
// echo server, send the data back
send(sd , buffer , len , 0 );
}
}
我在这段代码中看到的问题是 - 为什么我们认为/期望此send()
调用不会阻止?
即使我们执行套接字非阻塞,send()
也不会阻塞,但会发送部分数据甚至一无所有。
可能是我错了,但我认为我需要有数组字符串并使用writefds
直到发送数据等。
这有什么好的例子/做法吗?
答案 0 :(得分:3)
你担心send()
会阻止你是对的,因为它可以。
通常的解决方案是将套接字模式设置为非阻塞。然后,每次拨打send()
时,请检查是否:
errno
,看看它是EGAIN
还是EWOULDBLOCK
。如果发生其中任何一种情况,那么系统的套接字缓冲区已满,您需要在“等待”时将数据存储在某处,直到内核发送一些数据并释放系统套接字缓冲区中的空间。
现在,您将套接字添加到传递给writefds
的{{1}}数组,以要求系统在套接字再次可写时通知您。当select()
返回此套接字时,您应该尝试再次发送数据。如果在此期间有任何额外数据排队,请尝试发送。如果您可以发送所有数据,请从select()
数组中删除套接字(或者每次调用writefds
时都会返回该套接字。)