Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Синхронный (без блокировки) сокетсервер на Python? Как это собственно делается? 
:(
    Опции темы
HRustBB
Дата 27.7.2010, 17:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 26.5.2009

Репутация: нет
Всего: нет



Пока только изучаю вопрос. С целью ознакомления с темой пишу север, который собственно ничего особенно не делает, просто принимает данные от клиента. Вот код

Код

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
PM MAIL   Вверх
Void
Дата 27.7.2010, 17:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 10
Всего: 173



На listen-сокете нельзя делать recv. На нём можно сделать только accept, который вернёт новый сокет, через который уже можно общаться с клиентом.


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
HRustBB
Дата 27.7.2010, 21:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 26.5.2009

Репутация: нет
Всего: нет



забыл уточнить: у меня 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] Получен недопустимый аргумент

Так вот. Может у кого нибудь есть хотябы пример сервера без блокировки.

Это сообщение отредактировал(а) HRustBB - 27.7.2010, 21:30
PM MAIL   Вверх
Void
Дата 27.7.2010, 22:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 10
Всего: 173



Цитата(HRustBB @  27.7.2010,  23:27 Найти цитируемый пост)
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


Это сообщение отредактировал(а) Void - 27.7.2010, 22:24


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Python: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0651 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.