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
直到发送数据等
这方面有什么好的例子/做法吗?
您担心
send()
会阻塞是对的,因为它可以。
通常的解决方案是将socket模式设置为非阻塞。然后,每次调用
send()
时,检查是否:
errno
看看是EGAIN
还是EWOULDBLOCK
。如果发生其中任何一种情况,则系统的套接字缓冲区已满,您需要在“等待”内核发送一些数据并释放系统套接字缓冲区中的空间之前将数据存储在某个地方。
现在,您可以将套接字添加到传递给
writefds
的 select()
数组中,以要求系统在套接字再次变得可写时通知您。当 select()
返回此套接字时,您应该尝试再次发送数据。如果在此期间有任何额外的数据排队,请尝试发送该数据。如果您可以发送所有数据,请从 writefds
数组中删除套接字(否则每次调用 select()
时都会返回该套接字)。