SocketServer
The socketserver module simplifies the task of writing network servers.
There are four basic concrete server classes:
- class
socketserver.TCPServer(server_address, RequestHandlerClass, bind_and_activate=True) -
This uses the Internet TCP protocol, which provides for continuous streams of data between the client and server. If bind_and_activate is true, the constructor automatically attempts to invoke
server_bind()andserver_activate(). The other parameters are passed to theBaseServerbase class.
- class
socketserver.UDPServer(server_address, RequestHandlerClass, bind_and_activate=True) -
This uses datagrams, which are discrete packets of information that may arrive out of order or be lost while in transit. The parameters are the same as for
TCPServer.
- class
socketserver.UnixStreamServer(server_address, RequestHandlerClass, bind_and_activate=True) - class
socketserver.UnixDatagramServer(server_address, RequestHandlerClass,bind_and_activate=True) -
These more infrequently used classes are similar to the TCP and UDP classes, but use Unix domain sockets; they’re not available on non-Unix platforms. The parameters are the same as for
TCPServer.
These four classes process requests synchronously; each request must be completed before the next request can be started. This isn’t suitable if each request takes a long time to complete, because it requires a lot of computation, or because it returns a lot of data which the client is slow to process. The solution is to create a separate process or thread to handle each request; the ForkingMixIn and ThreadingMixIn mix-in classes can be used to support asynchronous behaviour.
There are five classes in an inheritance diagram, four of which represent synchronous servers of four types:
+------------+
| BaseServer |
+------------+
|
v
+-----------+ +------------------+
| TCPServer |------->| UnixStreamServer |
+-----------+ +------------------+
|
v
+-----------+ +--------------------+
| UDPServer |------->| UnixDatagramServer |
+-----------+ +--------------------+
Note that UnixDatagramServer derives from UDPServer, not from UnixStreamServer — the only difference between an IP and a Unix stream server is the address family, which is simply repeated in both Unix server classes.
- class
socketserver.ForkingMixIn - class
socketserver.ThreadingMixIn -
Forking and threading versions of each type of server can be created using these mix-in classes. For instance,
ThreadingUDPServeris created as follows:class ThreadingUDPServer(ThreadingMixIn, UDPServer): passThe mix-in class comes first, since it overrides a method defined in
UDPServer. Setting the various attributes also changes the behavior of the underlying server mechanism.
- class
socketserver.ForkingTCPServer - class
socketserver.ForkingUDPServer - class
socketserver.ThreadingTCPServer - class
socketserver.ThreadingUDPServer -
These classes are pre-defined using the mix-in classes.
Request Handler Objects
class
socketserver.BaseRequestHandlerThis is the superclass of all request handler objects. It defines the interface, given below. A concrete request handler subclass must define a new
handle()method, and can override any of the other methods. A new instance of the subclass is created for each request.setup()-
Called before the
handle()method to perform any initialization actions required. The default implementation does nothing.
handle()-
This function must do all the work required to service a request. The default implementation does nothing. Several instance attributes are available to it; the request is available as
self.request; the client address asself.client_address; and the server instance asself.server, in case it needs access to per-server information.The type of
self.requestis different for datagram or stream services. For stream services,self.requestis a socket object; for datagram services,self.requestis a pair of string and socket.
finish()-
Called after the
handle()method to perform any clean-up actions required. The default implementation does nothing. Ifsetup()raises an exception, this function will not be called.server端
1 import socketserver 2 3 class MyTCPHandler(socketserver.BaseRequestHandler): 4 """ 5 The request handler class for our server. 6 7 It is instantiated once per connection to the server, and must 8 override the handle() method to implement communication to the 9 client. 10 """ 11 12 def handle(self): 13 # self.request is the TCP socket connected to the client 14 self.data = self.request.recv(1024).strip() 15 print("{} wrote:".format(self.client_address[0])) 16 print(self.data) 17 # just send back the same data, but upper-cased 18 self.request.sendall(self.data.upper()) 19 20 if __name__ == "__main__": 21 HOST, PORT = "localhost", 9999 22 23 # Create the server, binding to localhost on port 9999 24 server = socketserver.TCPServer((HOST, PORT), MyTCPHandler) 25 26 # Activate the server; this will keep running until you 27 # interrupt the program with Ctrl-C 28 server.serve_forever()
client端
View Code1 import socket 2 import sys 3 4 HOST, PORT = "localhost", 9999 5 data = " ".join(sys.argv[1:]) 6 7 # Create a socket (SOCK_STREAM means a TCP socket) 8 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 9 10 try: 11 # Connect to server and send data 12 sock.connect((HOST, PORT)) 13 sock.sendall(bytes(data + "\n", "utf-8")) 14 15 # Receive data from the server and shut down 16 received = str(sock.recv(1024), "utf-8") 17 finally: 18 sock.close() 19 20 print("Sent: {}".format(data)) 21 print("Received: {}".format(received))
上面这个例子你会发现,依然不能实现多并发,哈哈,在server端做一下更改就可以了
把
1server=socketserver.TCPServer((HOST, PORT), MyTCPHandler)改成
1server=socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)