我是套接字编程的初学者,需要你的帮助。我已经使用 Python 文档中的 ThreadedTCPServer 示例实现了简单的回显服务器。它工作正常,但我有以下问题:
- 当客户端尝试发送零长度数据时,服务器挂起(在 socket.recv 中)。
- 当客户端发送的数据是 BUF_SIZE 的倍数时,服务器挂起(在 socket.recv 中)。
- 我不知道从外部停止服务器的正确方法。我想要一个脚本,例如 stopServer.py ,它可以在需要停止服务器时从服务器的主机启动。我已经实现了发送到服务器端口的“STOP”命令。这种方法对我来说看起来不错,但存在安全风险。请注意,我需要一个跨平台的解决方案。因此,信号可能不合适。
如果您对如何解决上面列出的问题有任何想法,我将不胜感激。该示例的代码如下所示。
祝你今天过得愉快!扎哈尔
客户端.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 ()
服务器.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 ()
常见的.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