同时使用accept()和select()?

Bor*_*lid 20 sockets network-programming tcp

我有一个事件驱动的网络服务器程序.此程序接受来自其他主机上其他进程的连接.在同一远程IP上可能存在来自不同端口的许多短期连接.

目前,我有一个while(1)循环调用accept()然后生成一个线程来处理新连接.读取消息后,每个连接都将关闭.在远程端,在发送消息后关闭连接.

我想通过缓存打开的套接字FD来消除设置和拆除连接的开销.在发送方,这很容易 - 我只是不关闭连接,并保持它们.

在接收方,它有点难.我知道我可以存储accept()在结构中返回的FD 并使用poll()或监听所有这些套接字上的消息select(),但我想同时通过所有缓存连接监听新连接accept() 监听.

如果我使用两个线程,一个打开poll(),一个打开accept(),那么当accept()调用返回(打开一个新连接)时,我必须唤醒另一个等待旧连接的线程.我知道我可以通过一个信号做到这一点pselect(),但是对于这么简单的事情来说,这整个混乱似乎太过分了.

有没有一个电话或更好的方法可以让我同时处理打开的新连接和旧连接上发送的数据?

mvd*_*vds 23

我上次检查时,你可以只是listen在一个套接字然后select或者poll看看是否有连接进来.如果是这样,accept它; 它不会阻塞(但你可能 真的应该设置O_NONBLOCK以确保)

  • 嗯,这是一个众所周知的竞争条件 - 如果客户端丢弃两个系统调用之间的连接尝试,`accept(2)`将阻塞.你*需要*监听套接字是非阻塞的. (9认同)
  • 这是正确的 - 您可以将您的监听文件描述符添加到`select()`调用中的`readfds`,而`select()`将告诉您文件描述符是"可读"的,如果它有一个准备好接受的连接()`.@Nikolai也是正确的 - 监听套接字应该是非阻塞的并且`accept()`调用准备好处理`EAGAIN`. (6认同)

Kha*_*led 5

你可以使用listen然后使用select或poll然后接受

if (listen (socket_fd, Number_connection) <0 )
{
    perror("listen");
    return 1;
}
fd_set set;
struct timeval timeout;
int rv;
FD_ZERO(&set); /* clear the set */
FD_SET(socket_fd, &set); /* add our file descriptor to the set */

timeout.tv_sec = 20;
timeout.tv_usec = 0;

rv = select(socket_fd + 1, &set, NULL, NULL, &timeout);
if(rv == -1)
{
    perror("select"); /* an error accured */
    return 1;
}
else if(rv == 0)
{
    printf("timeout occurred (20 second) \n"); /* a timeout occured */
    return 1;
}
else
    client_socket_fd = accept (socket_fd,(struct sockaddr *) &client_name, &client_name_len);
Run Code Online (Sandbox Code Playgroud)

  • 如果fd_set还有fds数据可能会被读取而不是正在侦听,该怎么办? (2认同)