我正在写一个TCP服务器(阻塞套接字模型)。
当服务器正在等待(阻止)接受Accept上的新连接尝试时,我无法实现有效的正常程序退出(我使用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退出。我尝试了几种不同的方法:
  • 尝试从另一个线程内使用m_Socket调用shutdown和/或closesocket失败(程序只是挂起)。
  • 使用WSAEventSelect的
  • 确实解决了此问题,但是WSAccept仅提供了非阻塞套接字-这不是我的意图。 (有没有一种方法可以使套接字阻塞?)
  • 我阅读了有关APC的内容,并尝试使用类似QueueUserAPC(MyAPCProc,m_hThread,1))的方法,但是它也不起作用。

  • 我究竟做错了什么 ?
    有没有更好的方法来使此阻塞WSAccept退出?

    最佳答案

    在超时之前使用select()来检测客户端连接实际上何时挂起,然后再调用WSAAccept()接受它。它与阻塞套接字一起工作,而无需将它们置于非阻塞模式。这将为您的代码提供更多机会检查应用程序是否已关闭。

    07-26 02:11