Я довольно новичок в программировании сокетов и не уверен насчет конкретного сценария c:
Допустим, у меня есть приложение (python), у которого открыт сервер сокетов и который прослушивает TCP 127.0 .0.1 порт 2030.
С помощью poll_interval это приложение может получать и обрабатывать 20 сообщений в секунду. Но третья сторона (которую я не могу контролировать) отправляет 40 сообщений в секунду.
Я заметил, что через некоторое время сервер сокетов приложений зависает и не может получить никакого нового соединения.
Я проверил состояние сокета на моей машине:
ss -pl | grep 2030
И видите, что в Recv-Q
есть сотни носков, которые не уходят.
root@mymachine:~# ss -l | grep 2030
tcp LISTEN 578 5 127.0.0.1:2030 *:*
Кроме того, я заметил сотни сокетов в состоянии close-wait
:
root@mymachine:~# netstat -ton | grep CLOSE_WAIT | grep 2030
tcp 580 0 127.0.0.1:2030 127.0.0.1:34200 CLOSE_WAIT off (0.00/0/0)
Это связано? И если да, то как защитить приложение сокета от пропускной способности, превышающей ожидаемую? / сек. Это по замыслу. Вопрос в том, как защитить приложения сокетов от пропускной способности, для которой они не предназначены.
В любом случае, я делюсь некоторым кодом:
socketserver.TCPServer.allow_reuse_address = True
server = socketserver.TCPServer((HOST, PORT), SocketHandler)
threading.Thread(target=server.serve_forever, kwargs={'poll_interval': 0.002}).start()
class SocketHandler(socketserver.BaseRequestHandler):
def handle(self):
data = self.request.recv(1500)
try:
decoded = data.decode("utf-8")
parsed = do_some_parsing()
if not parsed:
raise UnreadableMessage("Couldn't parse {}".format(data))
except UnreadableMessage as e:
logger.warning(e)
except Exception as e:
logger.error("Unknown exception occurred when tried to parse message: {]".format(data))
finally:
self.request.close()