私はソケットプログラミングの初心者で、あなたの助けが必要です. Python ドキュメントの ThreadedTCPServer の例を使用して、単純なエコー サーバーを実装しました。正常に動作しますが、次の問題があります。
- クライアントが長さゼロのデータを送信しようとすると、サーバーが (socket.recv で) ハングします。
- クライアントから送信されたデータが BUF_SIZE の倍数である場合、サーバーが (socket.recv で) ハングします。
- サーバーを外部から停止する正しい方法がわかりません。サーバーを停止する必要があるときに、サーバーのホストから開始できる stopServer.py などのスクリプトが必要です。サーバーのポートに送信される「STOP」コマンドを実装しました。このアプローチは私には良さそうに見えますが、セキュリティ上のリスクがあります。クロスプラットフォーム ソリューションが必要であることに注意してください。したがって、おそらく、信号は適切ではありません。
上記の問題を修正する方法についてご意見がありましたら、よろしくお願いいたします。例のコードを以下に示します。
良い1日を!ザカール
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 ()
サーバー.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