Index: SocketServer.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/SocketServer.py,v retrieving revision 1.26 diff -u -r1.26 SocketServer.py --- SocketServer.py 2001/07/24 20:34:08 1.26 +++ SocketServer.py 2001/07/28 17:41:35 @@ -110,15 +110,22 @@ BaseServer: - split generic "request" functionality out into BaseServer class. - Copyright (C) 2000 Luke Kenneth Casson Leighton example: read entries from a SQL database (requires overriding get_request() to return a table entry from the database). entry is processed by a RequestHandlerClass. +Test Method: +simple echo server, ForkingTCPServer and ThreadingTCPServer. +send data on port 10000, it will be received back, verbatim. +run test with --client to create 20 such test connections, +which will send 20 tests each and expect them to be received. + +TODO: write a UDPServer test, too. + """ -# Author of the BaseServer patch: Luke Kenneth Casson Leighton +# Author of the BaseServer and test() patch: Luke Kenneth Casson Leighton # XXX Warning! # There is a test suite for this module, but it cannot be run by the @@ -564,3 +571,171 @@ def finish(self): self.socket.sendto(self.wfile.getvalue(), self.client_address) + + +class EchoHandler: + """ an example handler that reads data from a socket + and sends it back. + """ + + def handle(self): + """ simple read line, write it. + we don't even do a select on the socket, just read + it. + """ + eof = None + data = None + + print 'received connection request' + data = self.rfile.readline() + print 'received data:', repr(data) + self.wfile.write(data) + self.wfile.flush() + +class EchoUDPHandler(EchoHandler,DatagramRequestHandler): pass +class EchoTCPHandler(EchoHandler,StreamRequestHandler): pass + + +class TestConnection: + """ simple test connector, has send and recv methods. + code is ripped / stripped from HTTPConnection :) + """ + + def __init__(self, host, port=None, socket_type=socket.SOCK_STREAM): + self.sock = None + self.host = host + self.port = port + self.socket_type = socket_type + + def connect(self): + """Connect to the host and port specified in __init__.""" + self.sock = socket.socket(socket.AF_INET, self.socket_type) + self.sock.connect((self.host, self.port)) + + # hmm, don't know enough about UDP / python to know if + # this works as expected! + self.fp = self.sock.makefile('wrb', 0) + + def close(self): + """Close the connection to the server.""" + if self.sock: + self.sock.close() # close it manually... there may be other refs + self.sock = None + + def send(self, str): + """Send `str' to the server.""" + if self.sock is None: + self.connect() + + try: + self.fp.write(str) + except socket.error, v: + if v[0] == 32: # Broken pipe + self.close() + raise + + def read(self, len=0): + """read from socket + """ + return self.fp.read(len) + + +def test(): + """ test method for SocketServer.py + """ + + def test_client_fn(server_addr='127.0.0.1', server_port=10000, + sock_type=socket.SOCK_STREAM): + + clients = [] + for n in range(20): + clients.append(TestConnection(server_addr, server_port, sock_type)) + + for i in range(len(clients)): + c = clients[i] + c.send("echo test %d\n" % i) + + for i in range(len(clients)): + c = clients[i] + expected_data = "echo test %d\n" % i + data = c.read(len(expected_data)) + if data != expected_data: + print "client %d failed test" + + + def test_server_fn(ServerClass, server_addr, HandlerClass): + + srv = ServerClass(('', 10000), HandlerClass) + srv.max_children = 50 + srv.serve_forever() + + def usage(): + print "usage: --client, -c a test client" + print " --thread-server, -t to run a threading server" + print " --fork-server, -f to run a forking server" + print " --udp, to run a UDP server" + print " --tcp to run a TCP server" + sys.exit(0) + + from getopt import getopt + + if len(sys.argv) == 1: + usage() + + opts, args = getopt(sys.argv[1:], 'hftc', + ['help', 'fork-server', 'thread-server', + 'udp', 'tcp', + 'client']) + + threading = None + forking = None + tcp = None + udp = None + testclass = None + testhandlerclass = None + sock_type = None + testclient = None + + for (opt, value) in opts: + + if opt == '--help' or opt == '-h': + usage() + + if opt == '--tcp': + tcp = 1 + sock_type = socket.SOCK_STREAM + + if opt == '--udp': + udp = 1 + sock_type = socket.SOCK_DGRAM + + if opt == '--fork-server' or opt == '-f': + forking = 1 + + if opt == '--thread-server' or opt == '-t': + threading = 1 + + if opt == '--client' or opt == '-c': + testclient = 1 + + if tcp and forking: + testclass = ForkingTCPServer + testhandlerclass = EchoTCPHandler + if tcp and threading: + testclass = ThreadingTCPServer + testhandlerclass = EchoTCPHandler + if udp and forking: + testclass = ForkingUDPServer + testhandlerclass = EchoUDPHandler + if udp and threading: + testclass = ThreadingUDPServer + testhandlerclass = EchoUDPHandler + + if testclass: + test_server_fn(testclass, 10000, testhandlerclass) + + if testclient: + test_client_fn('127.0.0.1', 10000, sock_type) + +if __name__ == '__main__': + test()