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

How to interrupt accept() in a TCP/IP server?

本文关键字:accept 中断 服务器 TCP IP      更新时间:2023-10-16

我正在开发一个视觉应用程序,它有两种模式: 1) 参数设置 2) 自动 问题出在 2) 中,当我的应用程序通过 TCP/IP 等待信号时。调用 -methode 时程序冻结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()

谢谢。

此致敬意

T

解决方案是仅在有传入连接请求时才调用accept()。您可以通过在侦听套接字上轮询来做到这一点,您还可以在其中添加其他文件描述符、使用超时等。

你没有提到你的平台。在Linux上,参见epoll(),UNIX参见poll()/select(),Windows I not know。

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

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

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

由于您尚未指定平台,并且网络(尤其是异步)是特定于平台的,因此我认为您需要一个跨平台的解决方案。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 可以是一个仅标头的库,并且在没有 Boost: http://think-async.com/Asio/AsioAndBoostAsio 的情况下使用。

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

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

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