Introduction: Experts often say that reading source code is a very efficient learning method. But for beginners like us, reading source code is a good way to master programming ideas and coding standards. In short, reading source code is not omnipotent, and not reading source code is absolutely impossible.
SocketServer is a very representative library in the standard library. It provides a framework for quickly establishing socket servers based on sockets, and can evolve single-threaded servers into multi-threaded or multi-process servers through Mix-in techniques. There are many classes in Socketserver.py. Let’s introduce them one by one and the relationship between them.
BaseServer, TCPServer, UDPServer, the former is the parent class of the latter two. The methods that can be shared by TCP and UDP servers are implemented in the parent class, leaving abstract classes that need to be implemented in the subclass. Therefore, in actual work, we generally should not inherit the BaseServer class unless you are implementing or overloading certain methods for yourself. In addition, UnixStreamServer and UnixDatagramServer inherit from TCPserver and UDPServer respectively. These two classes with the word Unix are used to build local socket servers under *nix (local socket access is faster, but can only be used for inter-process communication on the local machine)
Next are the two mixes of ForkingMixIn and ThreadingMixIn Classes, they both provide new implementations of the process_request method in the Server class. The former will start a new process when processing each user connection, while the latter will start a new thread. If you want the Server class to implement concurrent processing, just use multiple inheritance. Or use the already mixed
class ForkingUDPServer(ForkingMixIn, UDPServer): pass
class ForkingTCPServer(ForkingMixIn, TCPServer): pass
class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
class ThreadingTCPServer(ThreadingMixIn, TCPServer) ): pass
The last ones not introduced are BaseRequestHandler, StreamRequestHandler and DatagramRequestHandler. Like Server, the former is the parent class of the latter two to provide public methods
Usually when using SocketServer, we only instantiate a suitable Server ourselves. class, and pass its listening IP and port when instantiating it, as well as the class that was previously inherited from a RequestHandler (you need to implement the handle method yourself as the server's request handler)
Special attention needs to be paid here:
1. The IP and port are passed as a tuple rather than two separate parameters.
2. Each customer connection will be closed after the hanle method runs. If you don’t want to close it, you need to rewrite the def shutdown_request(self, request) method in the Server
____________________I am a gorgeous dividing line____________________
It can be said that this standard library is very convenient to use, but it still has some shortcomings in functionality.
1. It does not provide a communication mechanism between each handle instance, so clients still need to implement an observer model themselves to send messages to each other.
However, this function seems to exceed the job responsibilities of SocketServer. We can implement it ourselves, or we can use python-message, a domestic third-party library, to perform message-based programming between threads.
2. It provides a multi-threaded and multi-process solution, but the server without an asynchronous solution will be blocked every time it is accessed.
I feel very sorry about this, but this library is not too complicated. At worst, I can write one myself. Asynchronous socketserver, you can have enough food and clothing by yourself!
Because it is originally an interpretation of the source code, there is no code in this article. Readers can go to the standard library and look through it themselves. The comments are really well written.