Уведомления

Группа в Telegram: @pythonsu

#1 Ноя. 26, 2010 14:19:01

bezrukov Ilya
От:
Зарегистрирован: 2010-11-21
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

помогите разобраться с SocketServer

Приветствую.
Столкнулся с ошибкой при перезапуске примера из http://docs.python.org/library/socketserver.html#socketserver-tcpserver-example после подключения telnetom на порт 9999.

File "/usr/local/lib/python2.6/SocketServer.py", line 411, in server_bind
self.socket.bind(self.server_address)
File "<string>", line 1, in bind
socket.error: [Errno 98] Address already in use
смотрю что не так в SocketServer.py

.........
allow_reuse_address = False
.........
def server_bind(self):
"""Called by constructor to bind the socket.

May be overridden.

"""
if self.allow_reuse_address:
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind(self.server_address) # 411 строка
self.server_address = self.socket.getsockname()
вывод netstat
netstat -ne | grep 9999
tcp 0 0 127.0.0.1:9999 127.0.0.1:47237 TIME_WAIT 0 0
Вроде предусмотрен запуск сокета поверх TIME_WAIT - 410 строка, но ведь self.allow_reuse_address при запуске False.

Как запускать SocketServer чтобы вместо self.socket.bind(self.server_address) , вызывалась self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)



Офлайн

#2 Ноя. 26, 2010 14:30:06

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

помогите разобраться с SocketServer

В той же доке парой десятков строк выше:

BaseServer.allow_reuse_address
Whether the server will allow the reuse of an address. This defaults to False, and can be set in subclasses to change the policy.



Офлайн

#3 Ноя. 26, 2010 15:52:06

bezrukov Ilya
От:
Зарегистрирован: 2010-11-21
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

помогите разобраться с SocketServer

эх путаюсь я с этими классами, в общем заработало, но не уверен что я правильно сделал.

.....
SocketServer.TCPServer.allow_reuse_address=True
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)



Офлайн

#4 Ноя. 26, 2010 16:07:34

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

помогите разобраться с SocketServer

Так тоже можно, но правильно (по английски читаете?) переопределить в классе-наследнике.



Офлайн

#5 Ноя. 29, 2010 11:31:28

bezrukov Ilya
От:
Зарегистрирован: 2010-11-21
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

помогите разобраться с SocketServer

вот что у меня получилось - наверное это и есть это загадочное ООП).

в тот же файл примера добавляю свой класс

class MyTCPServer(SocketServer.TCPServer):

allow_reuse_address = 1

def __init__(self, host='localhost',
port=9999,
handler=MyTCPHandler):
SocketServer.TCPServer.__init__(self, (host, port), handler)
и вызываю его
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
server = MyTCPServer(host = HOST, port = PORT, handler = MyTCPHandler)
# Activate the server; this will keep running until you
# interrupt the program with Ctrl-C
server.serve_forever()



Офлайн

#6 Ноя. 29, 2010 15:20:15

bezrukov Ilya
От:
Зарегистрирован: 2010-11-21
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

помогите разобраться с SocketServer

Чем дальше в лес, тем больше дров.
столкнулся с новой трудностью, как завершить работу программы, например по приходу сообщения “exit”.

метод shutdown() напрямую не срабатывает.

def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
print "%s wrote:" % self.client_address[0]
print self.data
# just send back the same data, but upper-cased
self.request.send(self.data.upper())
if self.data=='exit':
self.shutdown()
#raise
скопипастил метод serve_until_stopped из примера для сервера логированияhttp://docs.python.org/library/logging.html#sending-and-receiving-logging-events-across-a-network
def serve_until_stopped(self):
import select
serving = 0
while not serving:
rd, wr, ex = select.select([self.socket.fileno()],
[], [],
self.timeout)
if rd:
self.handle_request()
serving = self.serving
но не пойму как обратиться к переменной self.serving из класса MyTCPHandler.

Я уже не знаю куда смотреть. в примерах вылезают потоки и черте что..
Спасибо за помощь



Офлайн

#7 Ноя. 29, 2010 15:41:36

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

помогите разобраться с SocketServer

class MyTCPServer(SocketServer.TCPServer):

allow_reuse_address = 1

def __init__(self, host, port):
SocketServer.TCPServer.__init__(self, (host, port), MyTCPHandler)

if __name__ == "__main__":
HOST, PORT = "localhost", 9999
server = MyTCPServer(HOST, PORT)
server.serve_forever()



Офлайн

#8 Ноя. 29, 2010 16:05:09

bezrukov Ilya
От:
Зарегистрирован: 2010-11-21
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

помогите разобраться с SocketServer

Андрей Светлов
Код:

class MyTCPServer(SocketServer.TCPServer):

allow_reuse_address = 1

def __init__(self, host, port):
SocketServer.TCPServer.__init__(self, (host, port), MyTCPHandler)

if __name__ == “__main__”:
HOST, PORT = “localhost”, 9999
server = MyTCPServer(HOST, PORT)
server.serve_forever()
Спасибо с этим надеюсь разобрался, я не могу понять как остановить server.serve_forever() по событию.
Например по приходу сообщения “exit” нужно остановить работу приложения.
Вызов метода self.shutdown() из def handle не срабатывает - нет такого метода у класса.

подсмотрел как можно остановить server.serve_forever() по Cntr-C или sys.exit()
def main():
HOST, PORT = "localhost", 9999
server = MyTCPServer(host = HOST, port = PORT, handler = MyTCPHandler)
print 'start server'
thr_server = threading.Thread(target=server.serve_forever)
thr_server.daemon = True
thr_server.start()

while 1:
try: time.sleep(3600)
except (KeyboardInterrupt, SystemExit):
print 'stop server'
server.shutdown()
break
return 0

if __name__ == "__main__":
sys.exit(main())
Теоретически я могу записывать входящие сообщения в файл, а потом ловить “exit” в нем - но как то хитро все это.



Офлайн

#9 Ноя. 30, 2010 11:19:24

bezrukov Ilya
От:
Зарегистрирован: 2010-11-21
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

помогите разобраться с SocketServer

Разобрался, в общем для того чтобы остановить .serve_forever(), пришлось использовать threading и задействовать глобальную переменную. Вместо глобальной переменной думаю есть еще варианты.

import SocketServer, time, threading

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()+'\n')

def finish(self):
global exit
if self.data=='exit':
exit = 1


class MyTCPServer(SocketServer.ThreadingTCPServer):

allow_reuse_address = 1

def __init__(self, host, port, handler):
SocketServer.ThreadingTCPServer.__init__(self, (host, port), handler)


def main():
global exit
exit = 0
HOST, PORT = "localhost", 9999
server = MyTCPServer(host = HOST, port = PORT, handler = MyTCPHandler)
thr_recv = threading.Thread(target=server.serve_forever)
thr_recv.daemon = True
print '%s started at %s' % (server.__class__.__name__, server.server_address)
thr_recv.start()
while not exit:
if exit:
print 'stop server'
server.shutdown()
break
time.sleep(5)
return 0


if __name__ == "__main__":
main()
Еще раз спасибо за помощь.



Офлайн

#10 Ноя. 30, 2010 11:26:00

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

помогите разобраться с SocketServer

Варианты всегда есть.
Просто, поймите правильно, socketserver - детская поделка. Много из него не выжмешь.



Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version