Синхронный (без блокировки) сокетсервер на Python?

 
0
 
Python
ava
HRustBB | 27.07.2010, 18:26
Пока только изучаю вопрос. С целью ознакомления с темой пишу север, который собственно ничего особенно не делает, просто принимает данные от клиента. Вот код


import socket

HOST = ''
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setblocking(0)
s.bind((HOST, PORT))
s.listen(10)

while(1):
try:
data = s.recv(1024)
except socket.error, errcode:
if errcode[0] == 35:
pass
else:
raise(socket.error)

s.close()


Не могу понять что тут не так, в IDLE запинается на строке except socket.error, errcode:. Кстати пример взял с wiki.linuxformat.ru
Kommentare (3)
ava
Void | 27.07.2010, 17:52 #
На listen-сокете нельзя делать recv. На нём можно сделать только accept, который вернёт новый сокет, через который уже можно общаться с клиентом.
ava
HRustBB | 27.07.2010, 21:27 #
забыл уточнить: у меня python 3.1

в книжке Д.Откидач про acept() написано:

accept() Принимает соединение и возвращает пару (conn, addr) где conn - новый объект сетевого соединения, подходящий для приема и посылки данных, addr - адрес другого конца сетевого соединения. Объект сетевого соединения, к которому применяется метод accept() должен быть привязан к адресу (метод bind) и ожидать соединения (метод listen).
А если я в IDLE пишу accept без предварительно написанного listen, то разумеется имею ошибку:

Traceback (most recent call last):
File "<pyshell#6>", line 1, in <module>
conn, addr = s.accept()
File "C:\Python31\lib\socket.py", line 120, in accept
fd, addr = self._accept()
socket.error: [Errno 10022] Получен недопустимый аргумент

Так вот. Может у кого нибудь есть хотябы пример сервера без блокировки.
ava
Void | 27.07.2010, 22:23 #
Цитата (HRustBB @ 27.7.2010, 23:27 findReferencedText)
accept() Принимает соединение и возвращает пару (conn, addr) где conn - новый объект сетевого соединения, подходящий для приема и посылки данных, addr - адрес другого конца сетевого соединения. Объект сетевого соединения, к которому применяется метод accept() должен быть привязан к адресу (метод bind) и ожидать соединения (метод listen).

И, что не так?

Ну вот пример, но он способен обрабатывать только одного клиента одновременно.

#!/usr/bin/python3

import socket
import select
import errno

HOST = ''
PORT = 50007

def handle_client(sock):
while True:
try:
data = sock.recv(4096)
if not data:
return
print(data)
except socket.error as err:
if err.errno == errno.EAGAIN:
pass
else:
raise

def main():
lSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
lSock.setblocking(0)
lSock.bind((HOST, PORT))
lSock.listen(10)
while True:
try:
sock, clientAddr = lSock.accept()
sock.setblocking(0)
try:
handle_client(sock)
finally:
sock.close()
except socket.error as err:
if err.errno == errno.EAGAIN:
pass
else:
raise

if __name__ == '__main__':
main()


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

import socket
import select
import errno

lSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
lSock.setblocking(0)
lSock.bind((HOST, PORT))
lSock.listen(10)
clients = {}
while True:
rfds = [lSock] + list(clients.values())
wfds = []
efds = []
readList, _writeList, _errList = select.select(rfds, wfds, efds, 0)
for sock in readList:
if sock == lSock:
try:
clientSock, clientAddr = lSock.accept()
clientSock.setblocking(0)
clients[clientSock.fileno()] = clientSock
except socket.error as err:
if err.errno == errno.EAGAIN:
pass
else:
raise
else:
try:
data = sock.recv(4096)
if not data:
del clients[sock.fileno()]
sock.close()
else:
print(data)
except socket.error as err:
if err.errno == errno.EAGAIN:
pass
else:
raise
Registrieren Sie sich oder melden Sie sich an, um schreiben zu können.
Unternehmen des Tages
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Mitwirkende
  Void   HRustBB
advanced
Absenden