我写了一个MFC C++应用程序,在该应用程序中,客户端进程通过TCP的
尝试一:在
尝试二:然后我尝试在后续的
在原型代码中,我仅仅销毁了监听套接字并重新创建了它,但对于生产代码来说,这是不可接受的,因为
MyCAsyncSocket::Connect
与服务器进程进行连接。服务器进程会响应MyCAsyncSocket::OnAccept
,并按照规定Detach
该套接字,创建一个线程并将其Attach
到该套接字上,然后读取正在发送的数据。MSDN指导将m_hSocket在Detach
之后设置为NULL。
这个方法可以正常工作,但仅限于第一次。第二次客户端尝试连接到相同的套接字地址时,没有OnAccept
通知。以下是服务器代码:void MyCAsyncSocket::OnAccept( int nErrorCode )
{
BOOL socketResult = FALSE;
CAsyncSocket syncSocket;
Accept( syncSocket );
AsyncSelect( FD_READ | FD_CLOSE );
SOCKET socket = syncSocket.Detach();
m_hSocket = NULL; // prescribed by msdn
... // go attach the socket in a worker thread, read the socket and do work
// try to re-establish listener.
...Create( // error: attempt 2: ASSERT(m_hSocket == INVALID_SOCKET)
endPoint.portNumber, // ok: same as client port number
SOCK_STREAM,
FD_READ | FD_WRITE | FD_ACCEPT | FD_CONNECT | FD_CLOSE,
endPoint.ipAddress // ok: same as client ip address
);
...Listen(); // error: attempt 1: no error case, but still doesn't work
CAsyncSocket::OnAccept( nErrorCode );
}
尝试一:在
Detach
之后的OnAccept
中,我尝试用Listen
进行后续操作,但是遇到了这个监听错误:“WSAENOTSOCK:描述符不是套接字”。不确定这是什么意思。尝试二:然后我尝试在后续的
Listen
之前进行Create
,但这导致了一个断言:ASSERT(m_hSocket == INVALID_SOCKET);
,其定义为:/*
* This is used instead of -1, since the
* SOCKET type is unsigned.
*/
#define INVALID_SOCKET (SOCKET)(~0)
在原型代码中,我仅仅销毁了监听套接字并重新创建了它,但对于生产代码来说,这是不可接受的,因为
Detach
和重新Attach
的整个概念是确保套接字线程的监听能力不会中断超过毫秒级。有人知道为后续的Connect
ion准备套接字的正确语义应该是什么吗?
AsyncSelect( FD_READ | FD_CLOSE );
和m_hSocket = NULL;
语句,第二个OnAccept
通知成功传递。当然,AsyncSelect( FD_ACCEPT | FD_READ | FD_CLOSE );
也可以工作。干得好。 - rtischer8277