Я пишу TCP-сервер в Windows NT, используя порты завершения для использования асинхронного ввода-вывода. У меня есть класс TcpSocket, класс TcpServer и некоторые (виртуальные функции) обратные вызовы для вызова после завершения операции ввода-вывода, например. onRead() для завершения чтения. У меня также есть onOpen(), когда соединение установлено, и onEof(), когда соединение закрыто, и так далее. У меня всегда есть отложенное чтение для сокета, поэтому, если сокет эффективно получает данные (чтение будет завершено с размером > 0), он вместо этого вызывает onRead(), если клиент закрывает сокет со стороны клиента em> (чтение будет завершено с размером == 0) он вызывает onEof(), и сервер знает, когда клиент закрывает сокет с помощью closesocket(server_socket); со своей стороны.
Все работает изящно, но я заметил одну вещь:
когда я вызываю closesocket(client_socket); на стороне сервера конечной точки соединения, а не на стороне клиента, (либо с настройкой linger {true, 0}, либо нет) отложенное чтение будет завершено как ошибочное, то есть размер чтения будет не только == 0, но также GetLastError() возвращает ошибку: 64 или «ERROR_NETNAME_DELETED». Я много искал об этом в Интернете, но не нашел ничего интересного.
Тогда я спросил себя: а настоящая ли это ошибка? Я имею в виду, можно ли это действительно считать ошибкой?
Проблема в том, что на стороне сервера обратный вызов onError() будет вызываться, когда я closesocket(client_socket); вместо onEof(). Поэтому я подумал так:
Что насчет того, если я при получении этой «ошибки» «ERROR_NETNAME_DELETED» вызову onEof() вместо onError()? Приведет ли это к некоторым ошибкам или неопределенному поведению? Еще один важный момент, который заставил меня задать этот вопрос, заключается в следующем:
Когда я получил это завершение чтения с «ERROR_NETNAME_DELETED», я проверил структуру OVERLAPPED, в частности, параметр перекрытия->Internal, который содержит код ошибки NTSTATUS базового драйвера. Если мы видим список кодов ошибок NTSTATUS [ http://www.tenox.tc/links/ntstatus.html ] мы можем ясно видеть, что «ERROR_NETNAME_DELETED» генерируется NTSTATUS 0xC000013B, что является ошибкой, но называется «STATUS_LOCAL_DISCONNECT». Ну, это не похоже на название ошибки. Это больше похоже на «ERROR_IO_PENDING», что является ошибкой, но также и статусом для правильного поведения.
Итак, как насчет проверки внутреннего параметра структуры OVERLAPPED, и когда он равен == 'STATUS_LOCAL_DISCONNECT', выполняется вызов обратного вызова onEof()? Испортит ли дело?
Кроме того, я должен сказать, что со стороны сервера, если я вызываю DisconnectEx() перед вызовом closesocket(client_socket); Я не получу эту ошибку. Но как насчет того, что я не хочу вызывать DisconnectEx()? Например. когда сервер выключается и не хочет ждать всех завершений DisconnectEx(), а просто хочет закрыть все подключенные клиенты.