скрипт с сокетами в python в какой-то момент сжирает ресурсы процессора - кажется, нужна помощь
я новичок (чорт, впору делать майки novichok)
сделал на питоне некий прокси-скрипт, который слушает на двух портах и потом передает услышанное клиенту на третьем порте. вроде бы все более-менее работает с одиночными подключениями, но в какой-то момент на рабочем ноуте, где пока что крутится скрипт, начинают завывать вентиляторы - и ресурсы жрет python, а сам скрипт как будто перестает работать.
есть подозрения, что криво написан обработчик входящих данных. идея заключается в том, чтобы находить во входящем потоке три байта, начинающиеся с \n, и сохранять в глобальную переменную второй и третий байты (в боевой версии кода это будет не \n, а 0, а остальные два байта никогда не будут равны 0)
#!/usr/bin/env python
import time, traceback
import logging
import threading
import SocketServer
import datetime
from threading import Thread
logging.basicConfig()
log = logging.getLogger('logger')
byte1 = 54
byte2 = 56
GPSString = "gps"
class CaaTHandler(SocketServer.StreamRequestHandler):
def handle_error(self):
log.error("opachki! oshibka")
def handle_timeout(self):
log.error("timeout!!!")
def handle(self):
self.request.settimeout(1)
global byte1
global byte2
reading = True
while reading:
# c = self.rfile.read(1)
c = self.request.recv(1)
if len(c)!=0:
print "read %d bytes: %r" % (len(c), c)
if len(c)!=0:
print "not empty!"
if c=="\n":
log.error("got cr")
c = self.request.recv(1)
if len(c)!=0:
byte1=ord(c)
log.error("got byte2")
log.error(c)
log.error(byte1)
c = self.request.recv(1)
if len(c)!=0:
log.error("got byte2")
log.error(c)
byte2=ord(c)
log.error(byte2)
if len(c)==0:
reading = False
class CaaSHandler(SocketServer.StreamRequestHandler):
def handle(self):
self.request.settimeout(1)
while 1:
now = datetime.datetime.now()
# data = self.rfile.readline()
time.sleep(1)
self.wfile.write(chr(byte1)+chr(byte2))
log.error("printing out bytes")
log.error(byte1)
log.error(byte2)
# self.wfile.write(str(now.second)+'\n')
class GPSHandler(SocketServer.StreamRequestHandler):
def handle(self):
reading = True
global GPSString
while reading:
GPSString = self.rfile.readline() #.rstrip('\r\n')
log.error(GPSString)
class MyThread(Thread):
def __init__(self, name):
Thread.__init__(self)
self.name = name
def run(self):
server = SocketServer.TCPServer(('', 50007), CaaSHandler)
server.serve_forever()
log.error("started service on port 50007")
class MyThread1(Thread):
def __init__(self, name):
Thread.__init__(self)
self.name = name
def run(self):
servet = SocketServer.TCPServer(('', 50008), CaaTHandler)
servet.serve_forever()
log.error("started service on port 50008")
class MyGpsListener(Thread):
def __init__(self, name):
Thread.__init__(self)
self.name = name
def run(self):
servgps = SocketServer.TCPServer(('',50009), GPSHandler)
servgps.serve_forever()
log.error("started service on port 50009")
def create_threads():
my_thread = MyThread("Sender")
my_thread.start()
log.error("started the first thread")
my_thread1 = MyThread1("Listener")
my_thread1.start()
log.error("started the second thread")
my_thread2 = MyGpsListener("GPSListener")
my_thread2.start()
log.error("started the third thread")
if __name__ == "__main__":
log.error("creating threads")
create_threads()
планирую запускать все это безобразие на роутере с томато-усб, и не хотелось бы, чтобы оно сжирало ресурсы. строчки с logger и print в финальном скрипте я скорее всего повыключаю. из того, что не нравится: 1. при отключении слушающего устройства (класс CaaS) - при запуске скрипта из терминала в терминал вываливается некий exception (как будто нештатная ситуация), при этом сам скрипт продолжает работать. 2. нет поддержки подключения сразу нескольких клиентов к одному порту. 3. когда рвется соединение к CaaT по таймауту - вроде бы все прекрасно, но если рву соединение подключенным клиентом - ловил подвисания, а в tcpdump какой-то ack пакет нулевой длины, если я правильно интерпретировал увиденное
и еще вопрос: если я запускаю этот скрипт в консоли - как правильно его отключать из этой же консоли (когда там кучка потоков) пока что вышел из положения, сделав из него в макоси сервис и загружаю/выгружаю с помочью launchctl - получается удобнее, чем многочисленные манипуляции с kill
UPD добавил костыль в виде отдельного треда-вочдога. по завершении чтения последнего байта сбрасываю вочдог. со вчерашнего вечера все работает и пока не хоггинга процессора не замечал. broken pipe не починил, но особо и не занимался. как выключать по-быстрому многотредовый скрипт из терминала, если в нем не предусмотрено соответствующих обработчиков - не разобрался. + новая напасть (ну то есть осознал) - после биндинга, когда делаем килл процесса, система не сразу освобождает занятые порты. в итоге перезапустить скрипт получается не сразу. хз как тут быть.