Нет уведомления OnAccept сервера при выполнении клиентского подключения во второй раз

Я написал приложение MFC C ++, где мой клиентский процесс делает TCP MyCAsyncSocket::Connect на мой серверный процесс. Серверный процесс отвечает MyCAsyncSocket::OnAccept который тогда DetachЕсли сокет, как это предписано, создает поток, который AttachЭто тот сокет, который затем читает отправляемые данные. MSDN предписывает, чтобы m_hSocket был установлен в NULL после Detach,

Работает нормально, но только один раз. Второй раз клиент пытается Connect на тот же адрес сокета, нет 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 workCAsyncSocket::OnAccept( nErrorCode );
}

Попытка 1: В OnAccept после Detach Я пытался следовать с Listen, но я получаю эту ошибку прослушивания: «WSAENOTSOCK: дескриптор не является сокетом». Не уверен, что это значит.

Попытка 2: затем я попытался сделать Create до продолжения Listen, но это вызвало утверждение: 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Ионы?

9

Решение

Если я правильно читаю, вы вызываете AsyncSelect (FD_READ | FD_CLOSE) на прослушивание сокет — и я думаю, что вы действительно хотите вызвать это на недавно принятом сокете (syncSocket).

Я ожидал бы, что вызов AsyncSelect (FD_READ | FD_CLOSE) может очистить уведомление FD_ACCEPT на слушающем сокете — таким образом гарантируя, что OnAccept не вызывается, когда будущие соединения сделаны с слушающим сокетом.

Далее — когда вы устанавливаете m_hSocket = NULL выше, вы обнуляете дескриптор прослушивание сокет, а не недавно принятый сокет (syncSocket).

Кроме того, если я правильно читаю MSDN (https://msdn.microsoft.com/en-us/library/05sz8hz8.aspx), сам метод Detach () обнуляет соответствующий дескриптор, и вам не нужно делать это самостоятельно. [и, я полагаю, вы не можете — так как m_hSocket должен быть частным членом syncSocket]

Я ожидаю, что ваш код OnAccept будет выглядеть примерно так:

void MyCAsyncSocket::OnAccept( int nErrorCode )
{
BOOL socketResult = FALSE;

CAsyncSocket syncSocket;

Accept( syncSocket );

SOCKET socket = syncSocket.Detach();

... // go attach the socket in a worker thread, which reads the socket and does work

}
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]