Python网络编程——SocketServer基础
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 theBaseServer
base 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,
ThreadingUDPServer
is created as follows:class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
The 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.
BaseRequestHandler
This 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.request
is different for datagram or stream services. For stream services,self.request
is a socket object; for datagram services,self.request
is 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端
1 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)