LINUX.ORG.RU

Сообщения puff

 

скрипт с сокетами в python в какой-то момент сжирает ресурсы процессора - кажется, нужна помощь

Форум — Development

я новичок (чорт, впору делать майки 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 не починил, но особо и не занимался. как выключать по-быстрому многотредовый скрипт из терминала, если в нем не предусмотрено соответствующих обработчиков - не разобрался. + новая напасть (ну то есть осознал) - после биндинга, когда делаем килл процесса, система не сразу освобождает занятые порты. в итоге перезапустить скрипт получается не сразу. хз как тут быть.

 , ,

puff
()

RSS подписка на новые темы