我是套接字編程的初學者,需要您的幫助。我使用Python文檔中的ThreadedTCPServer示例實現了簡單的回顯服務器。它工作正常,但我有以下問題:使用SocketServer實現網絡服務器的問題
- 當客戶端嘗試發送零長度數據時,服務器掛起(在socket.recv中)。
- 當客戶端發送的數據是BUF_SIZE的倍數時,服務器掛起(在socket.recv中)。
- 我不知道從外面停止服務器的正確方法。我想要一個腳本,例如stopServer.py,當需要停止服務器時,它可以從服務器的主機啓動。我實現了發送到服務器端口的「STOP」命令。這種方法對我來說看起來很不錯,但存在安全風險。請注意,我需要一個跨平臺的解決方案。所以,信號可能不適合。
如果您對如何解決上述問題有任何建議,我將不勝感激。 下面列出了該示例的代碼。
祝您有美好的一天! Zakhar
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
感謝您的回覆。關於「如果len(buf) BUF_SIZE」是不可能的情況。有關詳細信息,請參閱socket.recv python doc。 –
Zakhar
2010-10-05 06:26:44
recv調用通常返回由BUF_SIZE限制的套接字上可用的任何數據(在您的情況下)。正如我之前所說的,在TCP中,如果您在一個recv中發送BUF_SIZE數據,則無法保證您將通過一次recv呼叫來收回它們。 – 2010-10-05 14:23:06