Может ли ошибка Windows Socket # 10060 (WSAETIMEDOUT - попытка установить тайм-аут соединения без установления соединения) вообще быть ошибкой программирования? - PullRequest
0 голосов
/ 02 июля 2019

У меня есть приложение Delphi, использующее компоненты Indy HTTP (которое использует сокет Windows).И время от времени я получаю сообщение об ошибке # 10060 (WSAETIMEDOUT - попытка установить тайм-аут соединения без установления соединения) при выполнении процедуры Indy:

CheckForSocketError(IdWinsock2.Connect(ASocket, @LAddr, SizeOf(LAddr)));
...
connect : TconnectProc;
...
TconnectProc = function ( const s: TSocket; const name: PSockAddr; const namelen: Integer): Integer; stdcall;

На самом деле все это просто обтекание Windows connectфункция https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect, которая выдает ошибку и сообщение WSAETIMEDOUT.Итак, мой вопрос - это вообще может быть ошибка программирования?Даже если у меня есть сервер, работающий на другом компьютере, и даже у этого сервера возникают проблемы с обслуживанием запроса, даже в таких случаях низкоуровневое соединение должно работать нормально, если сервер не может обслуживать запрос GET / POST, тогда, конечно, ошибкидолжно быть, но эти ошибки должны возникать только во время выполнения других функций Socket, не входящих в функцию connect, не так ли?

Я пытаюсь решить мою проблему https://serverfault.com/questions/973648/is-it-possible-that-unencrypted-traffic-can-cause-windows-socket-10057-10060?noredirect=1#comment1266907_973648, и теперь яЯ ищу, что происходит в моем коде.

Мой код на стороне сервера очень прост - это просто компонент TIdHttpServer с внедренным (я предоставляю имя события только здесь):

MyForm.IdHTTPServerCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);

Итак - чтоможет быть проблема с моей реализацией, что может привести к появлению WSAETIMEDOUT для connect?Да, моя процедура иногда может быть долгой, но он годами возвращал ответ успешно и не было ошибок связи.И я полагаю, что функция соединения может даже не зависеть (не использовать / повышать) событие OnCommandGet, поэтому я не имею никакого контроля над тем, как серверная сторона обрабатывает функцию сокета от клиента?

Возможно, это связано с поддержанием активности TCP (не HTTP), возможно, некоторые обновления Windows сократили клиентские настройки поддержки активности Windows TCP для клиентов, и теперь это проявляется в такой ошибке.

1 Ответ

1 голос
/ 03 июля 2019

Indy TCP-клиенты, такие как TIdHTTP, имеют открытое свойство ConnectTimeout, которое по умолчанию установлено в 0 (бесконечно). Если время ожидания не указано, используется жестко заданное 2-минутное время ожидания, если клиентский метод TIdTCPClient.Connect() вызывается в основном потоке пользовательского интерфейса и TIdAntiFreeze активен, в противном случае время ожидания не используется.

Если используется тайм-аут, Indy вызывает функцию Winsock connect() в рабочем потоке и ожидает завершения этого потока. Если тайм-аут Indy истекает, сокет закрывается для отмены connect(), а затем EIdConnectTimeout повышается до вызывающей стороны. Если connect() завершается до истечения тайм-аута Indy, исключение выдается вызывающей стороне, только если connect() не удалось.

Если тайм-аут не используется, Indy вызывает Winsock connect() напрямую, ожидает его выхода по собственному желанию, а затем вызывает исключение только в случае сбоя.

Таким образом, ЕДИНСТВЕННЫЙ способ получить ошибку WSATIMEDOUT от Indy при вызове функции connect() Winsock - это если сам Winsock истек тайм-аут до истечения собственного тайм-аута Indy. Это не обязательно указывает на проблему в вашем коде. Это просто означает, что Host, к которому вы пытаетесь подключиться, просто недоступен в данный момент времени. Если бы сервер был доступен, но не смог принять ваше соединение, вы получите другую ошибку, такую ​​как WSAECONNREFUSED.

Если ваш сервер находится за брандмауэром или маршрутизатором, убедитесь, что он не блокирует соединения от доступа к вашему серверу. Попробуйте запустить анализатор пакетов на сервере, например WireShark, и убедитесь, что 3-стороннее TCP-квитирование от TIdHTTP правильно достигает сервера.

...