Я понимаю, что если я выполню вызов AcceptEx
через указатель функции, как это рекомендуется в документации, то, если я укажу размер буфера получателя, вызов не завершится, пока не будут отправлены некоторые данные:
if (!lpfnAcceptEx(sockListen,
sockAccept,
PerIoData->Buffer,
DATA_BUFSIZE - ((sizeof(SOCKADDR_IN) + 16) * 2), /* receive buffer size */
sizeof(SOCKADDR_IN) + 16,
sizeof(SOCKADDR_IN) + 16,
&dwBytes,
&(PerIoData->Overlapped)
))
{
DWORD dwLastError = GetLastError();
// Handle error
}
Из MSDN
Если буфер приема предоставлен, перекрывающаяся операция не будет завершена до тех пор, пока соединение не будет принято и данные не будут прочитаны. Используйте функцию getsockopt с параметром SO_CONNECT_TIME, чтобы проверить, было ли принято соединение.
Если сокет не подключен, getockopt возвращает 0xFFFFFFFF. Приложения, которые проверяют, завершена ли перекрывающаяся операция, в сочетании с параметром SO_CONNECT_TIME могут определить, что соединение принято, но данные не получены.
Такие соединения рекомендуется прерывать, закрывая принятый сокет, что приводит к завершению вызова функции AcceptEx с ошибкой.
Теперь это, кажется, означает, что я должен принудительно закрыть сокет. Однако в моей книге «Сетевое программирование для Microsoft Windows — второе издание» приводятся аналогичные факты, но далее говорится
В качестве предупреждения: приложения ни при каких обстоятельствах не должны закрывать дескриптор клиентского сокета, используемый в непринятом вызове AcceptEx, поскольку это может привести к утечке памяти. Из соображений производительности структуры режима ядра, связанные с вызовом AcceptEx, не будут очищаться при закрытии дескриптора неподключенного клиента до тех пор, пока не будет установлено новое клиентское соединение или пока не будет закрыт слушающий сокет.
Значит, мне нельзя закрывать его сейчас?? Я смущен.
Два вопроса:
1) Если сокет не полностью завершил AcceptEx
, я возвращаю 0xFFFFFFFF из getsockopt
. Это делает его кандидатом на принудительное закрытие. Но откуда мне знать, как долго он находится в таком состоянии? Я не могу добавить свою собственную логику синхронизации, потому что я не знаю, когда был сделан прием, потому что моя процедура порта завершения не завершена!
2) Когда я выясню, нужно ли мне закрыть сокет, как мне это сделать? Достаточно ли closesocket()
?