Есть ли способ сократить время ожидания connect_ex ()? - PullRequest
0 голосов
/ 25 июня 2019

Я пытаюсь устранить проблемы с подключением через сеть, пытаясь понять, почему некоторые пользователи могут видеть окно прямо при его включении, а другим может потребоваться около 20 секунд, чтобы увидеть его.Это вызывает некоторые фатальные проблемы в наших локальных программах.

С этой целью я запустил простой минимальный проверяемый скрипт на python, чтобы попытаться выяснить, в чем дело:

import socket
import time
import errno

HOST = '192.168.1.1'
PORT = 12345

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(1)

while(True):
   err = s.connect_ex((HOST, PORT))
   if err == 0:
      print("CONNECTED")
   else:
      print("NO CONNECTION: {0}".format(errno.errorcode[err]))
   time.sleep(2)

Когда я запускаю этокод, я вижу последовательный шаблон: EAGAIN, а затем 10 экземпляров EALREADY.Когда он СОЕДИНЯЕТСЯ, «СОЕДИНЕНО» заменяет бит EAGAIN цикла.

Я думал, что установка времени ожидания на 1 секунду и ожидание в течение 2 секунд должны позволить мне прервать вызов подключения в фоновом режиме,но это, кажется, не имеет никакого эффекта вообще.Есть ли опция TCP, которую я могу установить, или настройка Windows, которую я могу настроить, чтобы убедиться, что у меня нет этих неуклюжих 20-секундных блоков, пока я опрашиваю удаленный ящик на предмет подключения?

1 Ответ

1 голос
/ 25 июня 2019

При установке тайм-аута для сокета, socket.connect_ex() становится неблокирующей операцией. Вот почему вы получаете ошибки EAGAIN и EALREADY при повторном вызове connect_ex() в цикле - EAGAIN при первом вызове означает, что соединение не может быть установлено немедленно и выполняется в фоновом режиме, а затем EALREADY при последующих вызовах означает, что существующее соединение все еще выполняется и еще не завершено.

Ваш цикл просто выполняется до тех пор, пока соединение окончательно не завершится успехом или неудачей, независимо от того, сколько времени это займет. Таймаут сокета, который вы устанавливаете, не играет в эту логику.

Чтобы сделать то, что вы просите, запустите собственный таймер параллельно контуру соединения, а затем закройте сокет, если таймер истекает до того, как socket.connect_ex() вернет свой окончательный результат.

Либо вообще избавиться от петли.

Вызовите socket.connect_ex() один раз, и, если он вернет EAGAIN, введите select.select(), чтобы дождаться завершения соединения. Имеет параметр timeout. Сокет TCP перейдет в состояние записи, если ожидающая попытка подключения успешно подключится к серверу. Если select() истекло или сообщает об ошибке, закройте вместо этого сокет.

Или попробуйте использовать socket.create_connection(), который также имеет параметр timeout.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...