我是套接字编程的初学者,需要你的帮助。我使用Python文档中的ThreadedTCPServer示例实现了简单的echo服务器。它工作正常,但我有以下问题:
如果您对如何解决上面列出的问题有任何想法,我将不胜感激。 示例的代码如下所示。
祝你有愉快的一天! Zakhar
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 ()
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 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
答案 0 :(得分:2)
我不知道python,但我会根据我的套接字编程知识尝试回答。
零字节消息不会导致“sock.recv”出现。有关说明,请参阅here。如果sock.recv返回长度为0,则表示另一方已断开TCP连接。
if len (buf) < BUF_SIZE
此行如何确定已读取所有数据。 TCP recv呼叫不是TCP发送呼叫之间的1-1映射,即在多个recv呼叫中可以接收客户端发送的1个发送呼叫。
当您发送多个BUF_SIZE,即假设2 * BUF_SIZE时,您可能会一次性收到所有这些内容。此时,您的服务器将挂起len(buf) > BUF_SIZE
,您将陷入sock.recv。尝试&amp;弄清楚如何使用非阻塞套接字。
答案 1 :(得分:0)
经过一些实验后,我发现了以下内容:
需要在common.recv(bug)中注释以下两行:
if len (buf) < BUF_SIZE : # all data have been read
break