2016-09-21 4 views
1

У меня есть сервер заданий, который принимает запросы от клиента (есть 8 клиентов, отправляющих запросы с другого компьютера). Затем сервер отправляет «задание» («задание» - это просто исполняемый файл, который записывает файл результатов на диск), а в потоке «диспетчер заданий» ожидает выполнения задания. Когда задание выполняется, он отправляет клиенту сообщение о том, что файлы результатов готовы к копированию обратно клиенту.время чтения сокетов в recv

На главном потоке я использую select читать входящие соединения от клиентов, а также рабочие места запросы:

readable, writable, exceptional = select.select(inputs, [], []) 

, где inputs список принятых соединений (розеток), и этот список также включает в себя server разъем. Все сокеты установлены на неблокирующие. Для моего лучшего понимания, если этот вызов select возвращает непустую readable, это означает, что некоторые элементы inputs имеют входящие данные, ожидающие чтения. Читаю данные, используя следующую логику (SIZE константа):

for s in readable: 
    if s is not server: 
     try: 
      socket_ok = True 
      data = s.recv(SIZE) 
     except socket.error as e:   
      print ('ERROR socket error: ' + str(e)) 
      socket_ok = False 
     except Exception as e: 
      print ('ERROR error reading from socket: ' + str(e)) 
      socket_ok = False 
     if not socket_ok: 
      # do something 

У меня есть 2 проблемы:

  • Иногда я получаю [Errno 110] Connection timed out исключение, и я не понимаю, почему - если даже У меня есть читаемый сокет, разве это не значит, что у него есть данные для чтения?
  • Как бороться с этим исключением - часть #do something. Я могу выполнить «очистку» - удалить выполняемые задания, запрошенные таймером, и удалить мертвый сокет из списка. Но у меня нет возможности сообщить клиенту, что он должен прекратить ждать результатов этих заданий. В идеале я хотел бы как-то снова подключиться, потому что сами работы продолжают работать и дают результаты, которые я не хочу выбрасывать.

EDIT теперь я понял, что менеджер рабочих мест поток также имеет доступ к разъемам через Queue например - если работа закончена, поток посылает «работы» сообщения через соответствующий сокет - так может быть методы send и recv одного и того же сокета вызывают какое-то состояние гонки? Но в любом случае я не вижу, как это может привести к ошибке «время ожидания соединения».

+0

Попробуйте прочитать подробности здесь: https://pymotw.com/2/select/ –

+0

@ReutSharabani, я прочитал его, и на самом деле мой код основан на нем. Но в моем коде вы можете видеть, что это исключение возникает при чтении из сокета в списке 'readbale', а ссылка, о которой вы указали, означает:« Все сокеты в читаемом списке имеют входящие данные, буферизированные и доступные для чтения »- поэтому это не объясняет проблему, которую я имею –

ответ

0

Решение, которое было просто предположением и, похоже, работает: на стороне клиента я использую метод блокировки recv, чтобы получить сообщение с сервера о том, что задание выполнено. Поскольку задание может занять много времени (например, если на кластере, выполняющем задания, недостаточно ресурсов), я догадался, что, возможно, ожидание сокета стало причиной тайм-аута. Поэтому вместо использования recv в режиме блокировки я использую его с тайм-аутом 5 секунд, поэтому я могу отправлять фиктивное сообщение на сервер каждые 5 секунд, чтобы поддерживать соединение до получения сообщения. Теперь я больше не получаю исключение (на стороне сервера).

 Смежные вопросы

  • Нет связанных вопросов^_^