1

我正在编写一个 TCP/IP Socketserver。

我的问题是,当我(例如)远程登录我的服务器并且不发送任何数据时,我的接受呼叫被阻止并且不接受任何新的传入连接。

当我发送任何内容或退出 telnet 接受停止阻塞时,我可以处理发送的数据并接受开始接受新的传入连接。

main() {
   socket = bind_listen();

   while(1) {
       user_socket = accept(socket);
       ssl = SSL_new(ctx);
       SSL_set_fd(ssl, user_socket);
       SSL_accept(ssl);

       event.data.fd = user_socket;
       event.events = EPOLLIN | EPOLLONESHOT;

       epoll_proof = epoll_ctl(poll_fd, EPOLL_CTL_ADD, user_socket, &event);
   }
}

有几个线程用于 epoll_wait() 并处理数据。任何的想法?谢谢!

4

3 回答 3

2

那是因为你的程序是单线程的。在第一步中,它等待连接,之后,当连接建立时,它等待输入。
您有几个选项可以让它等待多个连接并全部接受它们:Threading、Select 和 fcntl。

于 2012-08-27T16:31:40.463 回答
1

您可以使用多路复用器,例如 select 或 poll 系列。

这将告诉您何时可以在不被阻止的情况下运行接受。

如果您不知道如何使用多路复用器,我认为 select 是最简单的解决方案:http: //linux.die.net/man/2/select

这也将避免诸如阻塞读/写之类的不良情况。

于 2012-08-27T16:29:23.493 回答
1

首先,您应该轮询侦听文件描述符(使用selectpollepoll/ kqueue)并且accept在准备好读取时才调用。

其次,更具体地说,如果您要使用 edge-triggered epoll,则需要先将套接字设置为非阻塞模式。然后,当您被告知它已准备好读取时,您需要accept循环调用,直到您返回-1错误EAGAINEWOULDBLOCK- 可能有多个连接请求同时等待,并且边缘触发轮询仅在状态更改时提醒您,所以你需要排空插座。

以一种非常非常幼稚的方式,您还可以取消轮询,而使用非阻塞套接字,无论是在繁忙的循环中还是在带有某种睡眠的循环中。epoll但这完全是浪费,与适当的/kqueue解决方案(或您的平台提供的任何轮询机制)相比,它不会给您带来任何好处。

于 2012-08-27T16:44:53.720 回答