2012-08-27 56 views
1

我正在编程一个TCP/IP套接字服务器。阻止接受

我的问题是,我接受呼叫阻塞和不接受任何新进来的连接时,我(例如)远程登录我的服务器和不发送任何数据。

当我发送任何或退出的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()和处理数据。 有什么想法?谢谢!

+1

显示您的代码,最好是可展示问题的最小可编译示例。 –

+0

没有提供足够的细节,但它听起来有点像你没有使用非阻塞套接字。 (在POSIX,这意味着'fcntl'设置'O_NONBLOCK',在Windows中,这意味着一些涉及'ioctlsocket',并在这两个这意味着处理上所有套接字调用'EAGAIN' /'EWOULDBLOCK'错误。) – asveikau

+0

我试图添加O_NONBLOCK但这并没有解决我的问题。 –

回答

1

首先,您应查询监听的文件描述符(与selectpollepoll/kqueue)和只有呼叫accept如果它是随时阅读。

其次,更具体地讲,如果你要为边沿触发epoll,您需要将您的插座中设置成非阻塞模式。然后,当有人告诉你,它已经准备好读,你需要调用accept在一个循环,直到你用错误EAGAINEWOULDBLOCK返回-1 - 有可能是在等待一次对多个连接请求,边沿触发轮询只提醒您开机状态变化,所以你需要排空插座。

在一个非常,非常幼稚的方式,你可以废除投票和与非阻塞套接字的工作,无论是在繁忙的循环,或与一种睡眠循环。但这是非常浪费的,并且与适当的解决方案(或者您的平台提供的任何轮询机制)相比,它不会为您购买任何东西。

1

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

这会告诉你,当你可以运行接受瓦特/出被封锁。

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

这也将避免坏的情况如阻塞读/写。

+0

所以我需要首先调用select或epoll,并首先等待套接字上的事件?当有一个事件我不得不接受()? –

2

这是因为你的程序是单线程的。在第一步中,它等待连接,然后在建立连接时等待输入。
有几个选项可以让它等待几个连接并接受它们:线程,选择和fcntl。