c++ - 解除阻止 WSAccept 以阻止 TCP 服务器套接字

标签 c++ sockets network-programming winsock

我正在编写一个 TCP 服务器(阻塞套接字模型)。 当服务器正在等待(阻塞)接受新的连接尝试(我使用 WSAccept)时,我无法实现有效的正常程序退出。 服务器的监听套接字的代码是这样的(我省略了错误处理和其他不相关的代码):

int ErrCode = WSAStartup(MAKEWORD(2,2), &m_wsaData) ;


// Create a new socket to listen and accept new connection attempts
struct addrinfo hints, *res = NULL, *ptr = NULL ;
int rc, count = 0 ;
memset(&hints, 0, sizeof(hints)) ;

hints.ai_family = AF_UNSPEC ;
hints.ai_socktype = SOCK_STREAM ;
hints.ai_protocol = IPPROTO_TCP ;
hints.ai_flags = AI_PASSIVE ;

CString strPort ;
strPort.Format("%d", Port) ;

getaddrinfo(pLocalIp, strPort.GetBuffer(), &hints, &res) ;

strPort.ReleaseBuffer() ;

ptr = res ;

if ((m_Socket = WSASocket(res->ai_family, res->ai_socktype, res->ai_protocol, NULL, 0, 0)) == INVALID_SOCKET)
{
    // some error   
} 

if(bind(m_Socket, (SOCKADDR *)res->ai_addr, res->ai_addrlen) == SOCKET_ERROR)
{
    // some error
}

if (listen(m_Socket, SOMAXCONN) == SOCKET_ERROR)
{
    // some error
}

到目前为止一切顺利...然后我在这样的线程中实现了 WSAccept 调用:

SOCKADDR_IN ClientAddr ;
int ClientAddrLen = sizeof(ClientAddr) ;

SOCKET TempS = WSAAccept(m_Socket, (SOCKADDR*) &ClientAddr, &ClientAddrLen, NULL, NULL);

当然 WSAccept 会阻塞,直到进行新的连接尝试,但如果我想退出 该程序然后我需要一些方法来使 WSAccept 退出。我尝试了几种不同的方法:

  1. 尝试从另一个线程中使用 m_Socket 调用 shutdown 和/或 closesocket 失败(程序只是挂起)。
  2. 使用 WSAEventSelect 确实解决了这个问题,但是 WSAccept 只提供非阻塞套接字——这不是我的意图。 (有没有办法让套接字阻塞?)
  3. 我阅读了有关 APC 的内容并尝试使用类似 QueueUserAPC(MyAPCProc, m_hThread, 1)) 的方法,但它也没有用。

我做错了什么? 是否有更好的方法使这个阻塞的 WSAccept 退出?

最佳答案

使用带超时的 select() 来检测客户端连接何时真正挂起,然后调用 WSAAccept() 接受它。它使用阻塞套接字而不将它们置于非阻塞模式。这将使您的代码有更多机会检查应用程序是否正在关闭。

关于c++ - 解除阻止 WSAccept 以阻止 TCP 服务器套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14361488/

相关文章:

c++ - 交叉依赖而不向前声明所有使用的功能?

c - 发送数据包时如何设置iptables标记?

c++ - TCP IOCP 在 acceptex 之后收不到

python - Python网络编程

c++ - C/C++ 中的简单 OpenSSL RSA 加密让我头疼

java - 如何在java中禁用证书验证

c# - 缓存友好优化 : Object oriented matrix multiplication and in-function tiled matrix multiplication

c++ - 您可以在 autoexp.dat 预览中使用连续的 #if block 吗?

c++ - 将一些输出重定向到命令提示符,将一些输出重定向到文件?

php - 在 PHP 中为 VTS 创建监听器套接字