Форум сайта python.su
Использую функцию select и одноименного модуля для того чтобы отслеживать “активные” сокеты, т.е. те с которых можно читать и в которые можно писать. Насколько я понял функция возвращает кортеж из трех списков - первый состоит из сокетов из которых можно что-то прочитать (т.е. которые у себя там вызвали send или connect и теперь можно получить их сообщения), второй список - в которые можно что-то написать (т.е. которые сделили у себя recv и теперь мы можем им что-то послать с помощью send). Однако, по-моему функция работает как-то неправильно. (или я что-то не правильно понял?)
Я пишу что-то типа:
mainSock = socket(AF_INET, SOCK_STREAM)
mainSock.bind(('', port))
mainSock.listen(10)
checkList = []
checkList.append(mainSock)
while True:
rl, rl2, rl3 = select.select(checkList, checkList, [])
for s in rl:
if s == mainSock:
client, adr = s.accept()
checkList.append(client)
else:
try:
print "Received: " + s.recv(maxLength)
except:
checkList.remove(s)
s = socket(AF_INET, SOCK_STREAM)
s.connect(("localhost", port)) # socket used to communicate to coordinator
for i in xrange(10):
s.send("PING?")
s.shutdown(0)
s.close()
Офлайн
Когда s.recv() возвращает пустую строку - значит писатель на другом конце отправил все данные и корректно закрыл соединение.
Отредактировано (Март 23, 2011 19:20:25)
Офлайн
Спасибо, это всё объясняет. Странно что в документации не упомянуто об этом :о(
Офлайн
Кстати, ещё пара вопросов остался не разрешенным.
1. Если я на сервер отправляю 10 раз одинаковое сообщение (см. пример выше), то почему они все принимаются серверов как одно большое? Можно ли их как-то “разделить”?
2. Почему клиентский сокет также оказывается в списке rl2, т.е. в списке содержащем сокеты в которые мы можем писать, я же не вызываю у клиента recv или что-то подобное? Как можно определить можно писать в сокет или нет?
Офлайн
1, потому что они передаются как поток, данные могут склеиться и могут разорваться в любом месте.
2. select предназначен для работы с блокирующими методами, а отправка данных не является блокирующим методом, отправлять можно в любой момент, метод send вернет кол-во отправленных байт, т.е. можно сделать так, имхо:
rl, rl2, rl3 = select.select(checkList, checkList, [])
Офлайн
1. способы разделения сообщений http://python.su/forum/viewtopic.php?pid=65262#p65262
2. Как работают сокеты? Для каждого сокета ОС создает два буфера - для записи (отправки) и чтения (приема) данных. Узнать размеры буферов можно так:
# send buffer
print s.getsockopt(SOL_SOCKET, SO_SNDBUF)
# recv buffer
print s.getsockopt(SOL_SOCKET, SO_RCVBUF)
Офлайн
o7412369815963забыл код поправить:
1, потому что они передаются как поток, данные могут склеиться и могут разорваться в любом месте.
2. select предназначен для работы с блокирующими методами, а отправка данных не является блокирующим методом, отправлять можно в любой момент, метод send вернет кол-во отправленных байт, т.е. можно сделать так, имхо:rl, rl2, rl3 = select.select(checkList, checkList, [])
rl, rl2, rl3 = select.select(checkList, [], [])
Офлайн
dimabestТогда, в случае если мне не надо отправлять данные, селект беспрерывно будет возвращать сокет. Оно так и есть?
В момент вызова select() операционная система для каждого сокета проверяет - можно ли дописать в буфер еще данных. Если да - возвращая сокет в write списке.
Офлайн
o7412369815963Функцию select мы просим проверить 3 списка:
Тогда, в случае если мне не надо отправлять данные, селект беспрерывно будет возвращать сокет
Отредактировано (Март 24, 2011 23:54:06)
Офлайн
Всем спасибо, кажется я всё понял.
Кстати, есть ли какие-нибудь библиотеки для сетевого взаимодействия, в которых есть более высокоуровенные операции, а все нюансы скрыты?
Офлайн