2016-11-16 9 views
0

Я реализую сокет-клиент, который одновременно открывает несколько сокетов. Любой сокет может иметь данные в другое время, и я хочу выполнить код, когда какой-либо сокет имеет данные и доступен для чтения.Как подождать, пока какой-либо сокет не получит данные?

Я не уверен, как это реализовать, я смотрел на select.select, но, похоже, дождался, когда все сокеты станут читабельными.

Я бы хотел, чтобы избежать использования многопроцессорной обработки данных в сокетах, я хотел бы, чтобы он был последовательным в чтении из каждого сокета, но читал, когда имеются данные.

Как подождать, пока какой-либо сокет будет доступен для чтения?

# psudo code 

sockets = [sock1, sock2, sock3] 

while True: 
    if len(sockets) == 0: 
    break 
    for sock in sockets: 
    if sock.has_data(): 
     do_stuff(sock) 
     sockets.remove(sock) 
    sleep(0.1) 
+2

'select' не ждет, когда все сокеты будут считаны читаемыми, он возвращается, когда один из них доступен для чтения. –

+2

Что бы вы ни делали, не забудьте установить неблокирующие сокеты, если вы не хотите блокировать их. Каждая функция, которую вы используете, будет функцией отчетности о состоянии, которая не может использоваться для прогнозирования будущего. Блокировка read * может * блокировать, независимо от того, что 'select' сказал. –

ответ

1

Вы можете использовать select.select для вашей проблемы:

sockets = [sock1, sock2, sock3] 
while sockets: 
    rlist, _, _ = select.select(sockets, [], []) 
    for sock in rlist: 
     do_stuff(sock) 
     sockets.remove(sock) 
+0

Просто не забудьте установить неблокирующие сокеты. –

+0

OP хочет блокировать, поскольку он удаляет сокет после выполнения каких-либо действий. – Daniel

+0

Правда, я хочу блокировать. Кроме того, спасибо Даниэлю, я думаю, что я просто ошибся с моей попыткой, я смог реализовать именно то, что хотел с выбором! :) – MatUtter

1

Если вы находитесь на POSIX, посмотрите на select.poll:

import socket 
import select 
p = select.poll() 
s1 = socket.socket() 
s2 = socket.socket() 
# call connect on sockets here... 
p.register(s1, select.POLLIN) 
p.register(s2, select.POLLIN) 
p.poll() 
1

Если вы используете Python 3.4 или более поздней версии в стандартной библиотеке есть модуль selectors. Он будет использовать «лучший» I/реализация O мультиплексирование, что ваша система предлагает (выбрать, опрос, Kqueue ...) Там простой пример эхо-сервера в конце документации страницы https://docs.python.org/3/library/selectors.html

Там в backport этого для более старые версии Python.