Dear Friends!
I am beginner in socket programming and need your help. I have implemented simple echo server using ThreadedTCPServer example from the Python documentation. It works fine, but I have the following problems: 1) Server hangs (in socket.recv) when Client tries to send zero-length data. 2) Server hangs (in socket.recv) when the data sent by Client is multiple of BUF_SIZE. 3) I don't know the right way to stop the server from the outside. I'd like to have a script, for example, stopServer.py which can be started from the server's host when need to stop the server. I've implemented "STOP" command which is send to the server's port. This approach looks good for me, but has security risk. Note that I need a cross-platform solution. So, probably, signals are not suitable. I will appreciate if you have any ideas how to fix the issues listed above. The example's code is listed below.
Have a nice day! 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