Уведомления

Группа в Telegram: @pythonsu

#1 Янв. 18, 2010 20:02:26

axe
От:
Зарегистрирован: 2008-08-07
Сообщения: 256
Репутация: +  0  -
Профиль   Отправить e-mail  

tcp socket client: основы

беру из документации пример:

import SocketServer
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
print "%s wrote:" % self.client_address[0]
print self.data
self.request.send(self.data.upper())

if __name__ == "__main__":
HOST, PORT = "localhost", 9999
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
если в handle() прописать:
conn, address = self.socket.get_request()
то conn - это новый объект типа socket. Если его хранить, то соединение с клиентом не будет закрываться.
не пойму, как правильно работать с этим объектом.

т.е. к серверу коннектится несколько клиентов, соединение с каждым храниться. и через эти соединения могут отправлятся некоторые данные. с этим вроде понятно: проходим по списку и для каждого делаем conn.send().
а чтобы обрабатывать входящие в сокеты данные - нужно что-то придумывать более серьёзное. Возникает желание, чтобы вместо объекта socket в get_request приходил объект моего класса, унаследованного от socket. Это возможно?



Офлайн

#2 Янв. 19, 2010 04:30:26

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

tcp socket client: основы

Можно переопределить TCPServer.get_request в потомке.
Наследоваться от socket - странная идея. Никогда не пробовал. Это же транспорт, а не протокол.
Я как-то для этих целей привык использовать twisted - а там все ясно и однозначно: Factory, Protocol, Transport.



Офлайн

#3 Янв. 19, 2010 12:35:49

axe
От:
Зарегистрирован: 2008-08-07
Сообщения: 256
Репутация: +  0  -
Профиль   Отправить e-mail  

tcp socket client: основы

Пробую все входящие в MyTCPHandler.handle запросы собирать в список.

cсначала делаю:

poll = select.poll()
conn = self.request ## объект типа socket
fileno = conn.fileno()## в документации рекомендовано к использованию в select
poll.register( fileno, POLLIN|POLLPRI|POLLERR|POLLHUP )
и кладу в conn в список

потом прохожу по списку:
            iwtd, owtd, ewtd = select.select( [fileno], [], [fileno], 1 )
if iwtd > 0 and not ewtd:
data = conn.recv(1024)
и в результате ошибка:
Exception in thread Thread-3:
Traceback (most recent call last):
File “/usr/lib/python2.5/threading.py”, line 486, in __bootstrap_inner
self.run()
File “/usr/lib/python2.5/threading.py”, line 663, in run
self.function(*self.args, **self.kwargs)
File “./server_socket.py”, line 40, in hello
data = conn.recv(1024).strip()
File “/usr/lib/python2.5/socket.py”, line 146, in _dummy
raise error(EBADF, ‘Bad file descriptor’)
error: (9, ‘Bad file descriptor’)
что я делаю не так?



Офлайн

#4 Янв. 19, 2010 13:28:01

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

tcp socket client: основы

Наверное, из списка еще и удалять нужно иногда :)
EBADF скорее всего говорит о том, что сокет уже закрыт.



Офлайн

#5 Янв. 19, 2010 13:29:32

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

tcp socket client: основы

Еще непонятно, зачем вы пытаетесь мешать poll и select



Офлайн

#6 Янв. 19, 2010 14:05:15

axe
От:
Зарегистрирован: 2008-08-07
Сообщения: 256
Репутация: +  0  -
Профиль   Отправить e-mail  

tcp socket client: основы

сокеты из списка удаляются в случае exception-а.
по поводу poll - я не особо умею им пользоваться. делаю по примеру. сейчас убрал его из совего тестового примера, - ничего не изменилось.

не понятно, почему сокеты закрываются.
т.е. если я получаю клиентский сокет через conn, addr = self.server.get_request(), то он живёт.
если я получаю через self.request, то соединение обрывается, не смотря на то, что объект продолжает существовать внутри списка.



Отредактировано (Янв. 19, 2010 14:29:24)

Офлайн

#7 Янв. 19, 2010 14:11:15

axe
От:
Зарегистрирован: 2008-08-07
Сообщения: 256
Репутация: +  0  -
Профиль   Отправить e-mail  

tcp socket client: основы

#!/usr/bin/python -t
# -*- coding: utf8 -*-

import SocketServer

from threading import Timer
from datetime import datetime
import sys
import select
f = open( '1.out', 'w' )
class F(object):
def __init__(self, f):
self.f = f

def write(self, x):
self.f.write(str(x)+"\n")
self.f.flush()

f = F(f)
class MySocket(object):
connList = []
def __init__(self, socket):
socket.makefile()
self.sock = socket
self.connList.append(socket)
sys.stdout = f
sys.stderr = f

@classmethod
def hello(cls):
for conn in cls.connList:
try:
fileno = conn.fileno()
iwtd, owtd, ewtd = select.select( [fileno], [], [fileno], 1 )
if iwtd > 0 and not ewtd:
data = conn.recv(1024).strip()
if data:
print data
conn.send(data.upper())
else:
f.write( "none" )
conn.send("none\n")
except Exception, e:
f.write(e)
cls.connList.remove(conn)
if not cls.connList:
f.write( "connList is empty" )
run()

def run():
t = Timer(2.0, MySocket.hello)
t.start()
run()

class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
MySocket(self.request)
self.request.settimeout(None)
print "new socket: ", self.client_address

HOST, PORT = "192.168.131.55", 9998
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
решил выложить полностью, чтобы в угадайку не играть



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version