poll / select和writefds的最佳实践

时间:2014-11-26 10:51:04

标签: c select

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直到发送数据等。

这有什么好的例子/做法吗?

1 个答案:

答案 0 :(得分:3)

你担心send()会阻止你是对的,因为它可以。

通常的解决方案是将套接字模式设置为非阻塞。然后,每次拨打send()时,请检查是否:

  1. 并非所有数据都已发送;或
  2. errno,看看它是EGAIN还是EWOULDBLOCK
  3. 如果发生其中任何一种情况,那么系统的套接字缓冲区已满,您需要在“等待”时将数据存储在某处,直到内核发送一些数据并释放系统套接字缓冲区中的空间。

    现在,您将套接字添加到传递给writefds的{​​{1}}数组,以要求系统在套接字再次可写时通知您。当select()返回此套接字时,您应该尝试再次发送数据。如果在此期间有任何额外数据排队,请尝试发送。如果您可以发送所有数据,请从select()数组中删除套接字(或者每次调用writefds时都会返回该套接字。)