如何在TCP / IP服务器中中断accept()?

时间:2017-05-30 10:15:49

标签: c++

我正在开发一个视觉应用程序,它有两种模式: 1)参数设置 2)自动 当我的应用程序通过TCP / IP等待信号时,问题出现在2)中。程序冻结而accept() - 方法被调用。我想在GUI上提供更改模式的可能性。因此,如果模式正在改变,则由另一个信号(message_queue)提供。所以我想打断接受状态。 是否有可能中断接受?

std::cout << "TCPIP " << std::endl;

client = accept(slisten, (struct sockaddr*)&clientinfo, &clientinfolen);

if (client != SOCKET_ERROR)
    cout << "client accepted: " << inet_ntoa(clientinfo.sin_addr) << ":"
         << ntohs(clientinfo.sin_port) << endl;

//receive the message from client
//recv returns the number of bytes received!!
//buf contains the data received
int rec = recv(client, buf, sizeof(buf), 0);
cout << "Message: " << rec << " bytes and the message   " << buf << endl;

我读到select(),但我不知道如何使用它。任何人都可以给我一个提示如何在我的代码中实现select()吗?

感谢。

致以最诚挚的问候,

Ť

4 个答案:

答案 0 :(得分:2)

解决方案是仅在有传入连接请求时调用accept()。您可以通过在侦听套接字上进行轮询来执行此操作,您还可以在其中添加其他文件描述符,使用超时等。

你没有提到你的平台。在Linux上,请参阅epoll(),UNIX请参阅poll()/ select(),Windows我不知道。

答案 1 :(得分:1)

一种方法是在超时循环中运行select

slisten置于非阻止模式(这不是绝对必要的,但有时accept阻止,即使select另有说明),然后:

fd_set read_fds;
FD_ZERO(&read_fds);
FD_SET(slisten, &read_fds);

struct timeval timeout;
timeout.tv_sec = 1;  // 1s timeout
timeout.tv_usec = 0;

int select_status;
while (true) {
    select_status = select(slisten+1, &read_fds, NULL, NULL, &timeout);
    if (select_status == -1) {
        // ERROR: do something
    } else if (select_status > 0) {
        break;  // we have data, we can accept now
    }
    // otherwise (i.e. select_status==0) timeout, continue
}

client = accept(slisten, ...);

这将允许您每秒捕获一次信号。更多信息:

http://man7.org/linux/man-pages/man2/select.2.html

和Windows版本(几乎相同):

https://msdn.microsoft.com/pl-pl/library/windows/desktop/ms740141(v=vs.85).aspx

答案 2 :(得分:0)

一般方法是使用本地TCP连接,UI线程可以通过该连接中断select调用。一般架构将使用:

  • select和本地TCP连接上等待slisten的专用线程
  • UI线程和等待线程之间的TCP连接(Unix或类Unix系统上的Unix域套接字,或Windows上的127.0.0.1)
  • 根据需要在两个线程之间进行各种同步/消息

只需声明select应该读取slisten和本地套接字。一旦准备就绪,它将立即返回,您将能够知道哪一个准备就绪。

答案 3 :(得分:0)

由于您尚未指定您的平台,并且网络(尤其是异步)是特定于平台的,因此我认为您需要跨平台解决方案。 Boost.Asio非常适合:http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/reference/basic_socket_acceptor/async_accept/overload1.html

链接示例:

void accept_handler(const boost::system::error_code& error)
{
  if (!error)
  {
    // Accept succeeded.
  }
}

...

boost::asio::ip::tcp::acceptor acceptor(io_service);
...
boost::asio::ip::tcp::socket socket(io_service);
acceptor.async_accept(socket, accept_handler);

如果Boost出现问题,Asio可以是仅限标头的lib,并且无需使用Boost:http://think-async.com/Asio/AsioAndBoostAsio