我正在写一个TCP服务器(阻塞套接字模型)。 当服务器在Accept(我使用WSAccept)等待(阻塞)新连接尝试时,我无法实现有效的正常程序出口。 服务器的监听套接字的代码是这样的(我省略了错误处理和其他不相关的代码):解除阻塞WSAccept阻止TCP服务器套接字
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退出。我尝试了几种不同的方法:
- 尝试从另一个线程中调用m_Socket的shutdown和/或closesocket失败(程序挂起)。
- 使用WSAEventSelect确实解决了这个问题,但是WSAccept只提供了非阻塞套接字 - 这不是我的目的。 (有没有办法让套接字阻塞?)
- 我阅读了关于APC并试图使用类似QueueUserAPC(MyAPCProc,m_hThread,1)的东西),但它也没有工作。
我在做什么错? 有没有更好的方法来阻止WSAccept退出?
我不能建议任何解决您的问题的简洁方法,但有一些讨厌的方法。 (1)退出进程并让操作系统清理套接字和其他活动句柄。 (2)设置关闭标志,然后连接到在accept调用中被阻塞的服务器,然后关闭此连接并干净地关闭。尽管如此,更好的方法是让接受的套接字非阻塞,并按照您的建议使用WSAEventSelect。 – simonc
通过使用Boost.Asio,这个实现看起来很可爱。 Asio有解决这个问题的方法。 –
在侦听套接字上调用shutdown是不合法的。 – EJP