Я новичок в программировании сокетов и мне нужна ваша помощь.Я реализовал простой эхо-сервер, используя пример ThreadedTCPServer из документации по Python.Он работает нормально, но у меня есть следующие проблемы:
- Сервер зависает (в socket.recv), когда Клиент пытается отправить данные нулевой длины.
- Сервер зависает (в сокете.recv) когда данные, отправленные Клиентом, кратны BUF_SIZE.
- Я не знаю, как правильно остановить сервер извне.Я хотел бы иметь скрипт, например, stopServer.py, который может быть запущен с хоста сервера, когда нужно остановить сервер.Я реализовал команду "STOP", которая отправляется на порт сервера.Этот подход выглядит хорошо для меня, но имеет риск для безопасности.Обратите внимание, что мне нужно кроссплатформенное решение.Так что, вероятно, сигналы не подходят.
Буду признателен, если у вас есть идеи, как решить проблемы, перечисленные выше.Код примера приведен ниже.
Хорошего дня!Захар
client.py
import sys
import socket
from common import recv
if len (sys.argv) == 1 :
print "The file to be sent is not specified"
sys.exit (1)
fname = sys.argv [1]
print "Reading '%s' file..." % fname,
f = open (sys.argv [1])
msg = f.read ()
f.close()
print "OK"
if len (msg) == 0 :
print "Nothing to send. Exit."
sys.exit (0)
print "Client is sending:"
print msg
print "len (msg)=%d" % len (msg)
sock = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
sock.connect ( ('localhost', 9997) )
sock.sendall (msg)
print "Sending has been finished"
print "Waiting for response..."
response = recv (sock)
print "Client received:"
print response
print "len (response)=%d\n" % len (response)
sock.close ()
server.py
import threading
import SocketServer
from common import recv
class ThreadedTCPRequestHandler (SocketServer.BaseRequestHandler):
def handle(self) :
recvData = recv (self.request)
print "NEW MSG RECEIVED from %s" % self.client_address [0]
print "Data:"
print recvData
print "dataSize=%d" % len (recvData)
if recvData == "!!!exit!!!" :
print 'Server has received exit command. Exit.'
self.server.shutdown()
else :
curThread = threading.currentThread ()
response = "%s: %s" % (curThread.getName (), recvData)
self.request.sendall (response)
class ThreadedTCPServer (SocketServer.ThreadingMixIn, SocketServer.TCPServer) :
pass
if __name__ == "__main__":
HOST, PORT = "localhost", 9997
server = ThreadedTCPServer ((HOST, PORT), ThreadedTCPRequestHandler)
server.serve_forever ()
common.py
'''
Common code for both: client and server.
'''
def recv (sock) :
'''
Reads data from the specified socket and returns them to the caller.
IMPORTANT:
This method hangs in socket.recv () in the following situations (at least
on Windows):
1. If client sends zero-length data.
2. If data sent by client is multiple of BUF_SIZE.
'''
BUF_SIZE = 4096
recvData = ""
while 1 :
buf = sock.recv (BUF_SIZE)
if not buf :
break
recvData += buf
if len (buf) < BUF_SIZE : # all data have been read
break
return recvData