程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python official document translation_ Socketserver module

編輯:Python

socketserver – Web server framework

socketserver Module simplifies the task of writing a web server

socketserver There are four basic server classes in the module :

  • class socketserver.TCPServer(server_address, RequestHandlerClass, bind_and_activate=True)
    This class uses TCP agreement (Transmission Control Protocol Transmission control protocol ), This protocol provides continuous data flow between the server and the client , If bind_and_activate by True, The constructor will automatically attempt to call server_bind() and server_activate() Method . Other parameters are passed to its parent class BaseServer
  • class socketserver.UDPServer(server_address, RequestHandlerClass, bind_and_activate=True)
    This class uses UDP agreement (User Datagram Protocol User datagram protocol ), This protocol sends discontinuous packets , The order in which these packets arrive at the destination may be different from the order in which they are sent , During transmission , Packets can also be lost . Its parameters are similar to TCPServer equally .
  • class socketserver.UnixStreamServer(server_address, RequestHandlerClass, bind_and_activate=True)
    class socketserver.UnixDatagramServer(server_address, RequestHandlerClass, bind_and_activate=True)
    These two classes are not commonly used , Similar to the above two classes , But it uses Unix Domain socket ( original text Unix domain socket I wonder if the translation is correct ), They are in Africa Unix Platform unavailable . Their parameters are similar to TCPServer equally .

The above four classes are Sync Processing network requests , in other words , After processing a request , To continue processing the next request . In some cases , For example, processing a request requires a lot of computation , Or the server needs to return a large amount of data and the client is slow to process , It takes a long time to process a request , that , Simply using the above four classes is not appropriate . The solution is to create separate processes or threads to handle time-consuming tasks ,ForkingMixIn and ThreadingMixIn These two mixed classes (mix-in class) Can be used to support asynchronous Behavior .

Creating a web server requires several steps :

  1. Create a Request processor class (request handler class), This class inherits from BaseRequestHandler class , And need to rewrite its handle() Method , This method is used to process incoming requests
  2. Instantiate a Server class ( One of the four classes mentioned above ), Pass in Server address and Request processor class As a parameter , Make a proposal to Server object And with Statement collocation
  3. call Server object Of handle_request() perhaps serve_forever() Method , To handle one or more requests
  4. call server_close() Method to close socket( Of course , If you use with sentence , There is no need to manually shut down the server )

When mixed ThreadingMinIn Class to add multi-threaded connection behavior , You need to make it clear that when the server encounters an unexpected shutdown , How your thread should handle .ThreadingMixIn Class defines a deamon_threads attribute , This attribute determines whether the server waits for the thread to terminate . If you want your server to automatically handle waiting threads , You need to explicitly set this property , The default value for this property is False, This means that the thread is not a daemon thread ,True Indicates that the thread is a daemon thread .( When all Non-daemon thread When they all quit ,python I'll quit )

For the four basic server classes mentioned earlier , No matter what network protocol they use , Their exposed methods and properties are the same .

Considerations for creating servers

There are five classes in the following inheritance diagram , Four of these classes are four types of synchronization server classes

Be careful UnixDataframServer Class inherits from UDPServer, Not inherited from UnixStreamServer, The only difference between them is the address family (adress family) The difference between

class socketserver.ForkingMixIn
class socketserver.ThreadingMixIn
Multi process and multi-threaded versions of each type of server class , You can do this by mixing the above two classes , For example, a multithreaded UDP The server class can be created in the following way :

class ThreadingUDPServer(ThreadingMixIn, UDPServer):
pass

Mixed type (ThreadingMixIn) Must be at the top of the inheritance list , So that it can cover UDPServer Class method . By setting the properties provided by the mixed type , Can change the behavior of the underlying server mechanism .

As mentioned below ForkingMixIn Class and others Forking Classes can only support fork() Of POSIX Use under platform .

  • socketserver.ForkingMixIn.server_close()
    This method will wait for all child processes to complete before shutting down the server , Unless socketserver.ForkingMixIn.block_on_close Property is set to False
  • socketserver.ThreadingMixIn.server_close()
    This method waits for all non - daemon threads to complete , Shut down the server , Unless socketserver.ThreadingMixIn.block_on_close Property is set to False.
    By setting ThreadingMixIn.daemon_threads by True You can set the thread as a daemon thread ( That is, the server will not wait for this thread to complete before exiting )

Python 3.7 New changes in version :
socketserver.ForkingMixIn.server_close()
socketserver.ThreadingMixIn.server_close()
These two methods will now wait for all child processes and non daemon threads to complete before exiting
And added a
socketserver.ForkingMixIn.block_on_close
attribute , To selectively add 3.7 Behavior before version

class socketserver.ForkingTCPServer
class socketserver.ForkingUDPServer
class socketserver.ThreadingTCPServer
class socketserver.ThreadingUDPServer
These predefined classes are defined using the above hybrid classes

Implement a service , You need to subclass BaseRequestHandler And rewrite it handle() Method . By combining certain types of server classes , You can run many types of services . The request processor class must be different from the server class . Of course, these details can be ignored , Instead, use existing classes directly StreamRequestHandler and DatagramRequestHandler.

Of course , You still need to use your head . such as , Multiprocess server The processes of will keep their own status information copy , Changes to the status information do not affect other processes , Other processes will not be aware of the state information changes , In this case ( Need to share data ), Consider using Multithreaded server class , however , Since shared data is involved , You have to consider using Thread lock To solve Data synchronization The problem of .

On the other hand , If you're building one HTTP The server , All data of the server is stored externally ( For example, it is stored in the file system ), In this case , When the server is busy processing a request , This server will actually become a …“ Deaf person ”( It means it can't hear any other requests ), Especially when the request being processed takes a long time , Or when the client receives data very slowly , In situations like this , Using a multi-threaded or multi process server is better .

In some cases , Synchronous processing part of the request , The rest is put into a new process , It might be more appropriate . This can be done in a Synchronization server Of Request processor class Of handle() Method to explicitly create a new process to implement .

If an environment supports neither multithreading nor multiprocessing ( It may be too expensive to support these functions , Or it is not suitable for this server ), There is another way to handle highly concurrent requests : Maintain a clear record of outstanding requests , Use selectors To decide which request in the table should be processed next , Or whether to process a new request . This is especially important for servers that provide streaming services , Because its client may be connected for a long time ( If multithreading or multiprocessing is not supported ),asyncore Module provides another way to deal with such problems .

Server object

class socketserver.BaseServer(server_address, RequestHandlerClass)

This is the parent of all other server classes in this module . It defines a common interface , Most of the underlying but not implemented methods , These methods will be implemented in subclasses . The two parameters are stored in server_address and RequestHandlerClass Properties of the .

  • fileno()
    Returns the of the socket that the server is listening on int File descriptor of type . Usually , This function is passed to the selector (selectors), To allow listening to multiple servers in the same process .

  • handle_request()
    Process a single request . This function calls the following methods in sequence :
    get_request()
    verify_request()
    process_request()
    If the request provided by the user handles handle() Method throws an exception , that handle_error() Method will be called .
    If in timeout No requests received within seconds , be handle_timeout() Will be called ,handle_request() Returns the

  • serve_forever(poll_interval=0.5)
    If you do not receive a definite shutdown() request , Just keep processing requests .
    every other poll_interval Poll once per second .
    Ignore timeout attribute .
    It will also call service_actions(), This method is used by subclasses or hybrid classes to add operations specific to a particular service . such as ,ForkingMixIn Class with service_actions() To clean up zombie child processes
    Python 3.3 The change of
    by serve_forever Method add service_actions Method

  • service_actions()
    This method is serve_forever() Method is called .
    This method can be overridden by subclasses or mixed classes , To provide exclusive operations for specific services , Such as cleaning operation
    Python 3.3 Version newly added

  • shutdown()
    Give Way serve_forever() Loop exit , And wait for it to exit
    shutdown() Must be between and serve_forever() Call in different threads , Otherwise, it will cause Deadlock .

  • server_close()
    Clean up the server , Can be rewritten .

  • address_family
    This attribute indicates the protocol family to which the socket of the server belongs , Common are :
    socket.AF_INET
    socket.AF_UNIX

  • RequestHandlerClass
    User provided request processor class , For each request , Will create an instance of this class .

  • server_address
    The address the server listens to .
    Different protocol families have different address formats , see socket Module documentation for more detailed information
    about IP agreement , An address is a tuple with two elements : A string type IP Address and an integer type port number , for example (‘127.0.0.1’,80)

  • socket
    Socket on which the server listens for incoming requests

The above server classes support the following class variables :

  • allow_reuse_address
    Whether the server allows the reuse of an address . This variable defaults to False, And can be set in subclasses , To change the strategy
  • request_queue_size
    The size of the request queue . If the server takes a lot of time to process a request , When the server is busy, incoming requests will be put into a queue , This queue can hold up to request_queue_size A request . Once the queue is full , Subsequent requests will get a “ Connection refused ”(Connection denied) Error of . The default value of the variable is 5, But you can override... In subclasses .
  • socket_type
    The type of socket used by the server , The usual value is :
    socket.SOCK_STREAM
    socket.SOCK_DGRAM
  • timeout
    Timeout time , In seconds , Set to None Indicates that no timeout is required .
    If handle_request() Method in timeout No incoming requests were received within seconds , be handle_timeout() Method will be called .

There are also server methods , Can be BaseServer Subclasses of ( such as TCPServer) Rewritten . These methods are for external users of the server object , No eggs .

  • finish_request(request, client_address)
    This is where the request is actually processed , Responsible for instantiation RequestHandlerClass And call the... Of this instance handle() Method
  • get_request()
    Must accept a request from a socket , And returns a binary containing the new socket object and the client address .
  • handle_error(request, client_address)
    When RequestHandlerClass Example of handle() Method throws an exception (Exception) when , This method will be called . The default behavior is to print trace stack information to the standard error stream , And continue to process subsequent requests .
    Python 3.6 The change of :
    Only when thrown by Exception Derived exception , This method is called .
  • handle_timeout()
    When timeout Property sets a non None Value , And more than timeout No request has been received after time , Then this method will be called . On a multi process branch server , The default behavior is to collect the status of all child processes that have exited , On a multithreaded server , This method does nothing .
  • process_request(request,client_address)
    call finish_request() Method to instantiate RequestHandlerClass. This method can also be overridden by subclasses , Create a new process or thread to process requests .ForkingMixIn and ThreadingMixIn Class already does these things .
  • server_activate()
    Called by the server's constructor , To activate the server . stay TCP Server , The default behavior of this method is to call the socket object listen() Method . Can be overridden by subclass .
  • server_bind()
    Called by the server's constructor , Bind the socket to the specified address , Can be overridden by subclass .
  • verify_request(request, client_address)
    Must return a Boolean value ; return True, Then the request will be processed , return False, The request will be rejected . This method can be overridden , It is used to realize the access control of the server . The default always returns True.
    Python 3.6 The change of :
    Added support for the context manager protocol ( namely with Sentence block ).
    Exiting the context manager is equivalent to calling server_close() Method .

Request processor object

class socketserver.BaseRequestHandler

This is the superclass of all request processor classes . It defines the underlying interface .
A concrete request handler subclass must implement the new handle() Method , And rewrite some other methods .
For each request , Will create a new subclass instance

  • setup()
    stay handle() Call before method , To perform some necessary initialization actions .
    The default implementation does nothing .
  • handle()
    All the work required to service a request is done by this function .
    The default implementation does nothing .
    it ( It should refer to the request processor object ) There are several instance properties available , Can be used to access server information :
    self.request request
    self.client_address Client address
    self.server Server object instance
    For datagrams (datagram) And flow (stream) For service , They correspond to self.request There are different types of .
    For streaming services ,self.request Is a socket object
    For datagram Services ,self.request Is a binary containing a string and a socket object .
  • finish()
    stay handle() Then call , Perform some necessary cleanup .
    The default implementation does nothing .
    If setup() Throw an exception , This function will not be called .

class socketserver.StreamRequestHandler

class socketserver.DatagramRequestHandler

these BaseRequestHandler The subclass of overridden setup() and finish() Method , And to provide self.rfile and self.wfile attribute .
self.rfile and self.wfile Property can read data separately or return data to the client .
Of these two classes rfile Property support io.BufferedIOBase Readable interface .
Of these two classes wfile Property support io.BufferedIOBase Writable interface .
Python 3.6 The change of :
StreamRequestHandler.wfile Also support io.BufferedIOBase Writable interface .

Example

socketserver.TCPServer Example

This is the server side :

import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
""" Our server's request processor . For each connection , The request processor will be instantiated once , And it must be rewritten handle() Method to communicate with the client . """
def handle(self):
# self.request Is connected to the client TCP Type socket 
self.data = self.request.recv(1024).strip()
print("{} wrote:".format(self.client_address[0]))
print(self.data)
# Only the same content is returned here , Just converted to uppercase 
self.request.sendall(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
# Create a server , Bound to the localhost Of 9999 port 
with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
# Start the server , This time keep the server running , Instruct you to use Ctrl + C To terminate the program 
server.serve_forever()

An alternative to the request processor class that utilizes streams ( This is a class file object , Simple communication with the client through the same interface as the standard file object )

class MyTCPHandler(socketserver.StreamRequestHandler):
def handle(self):
# self.rfile Is a class file object created by the request processor ;
# We can use readline() To replace the original recv() call 
self.data = self.rfile.readline().strip()
print("{} wrote:".format(self.client_address[0]))
print(self.data)
# Allied , self.wfile Is a class file object used to write data back to the client 
self.wfile.write(self.data.upper())

The difference between them is : Of the second processor readline() Method will call recv() Method , Until you encounter a newline character ; However , Of the first processor recv() Method will return the sendall() Method .

This is the client :

import socket
import sys
HOST, PORT = "localhost", 9999
data = " ".join(sys.argv[1:])
# Create socket (SOCK_STREAM representative TCP Socket )
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
# Connect to the server and send data 
sock.connect((HOST, PORT))
sock.sendall(bytes(data + "\n", "utf-8"))
# Receive data from the server , Then close it 
received = str(sock.recv(1024), "utf-8")
print("Sent: {}".format(data))
print("Received: {}".format(received))

The output of this example should look like this :
The server :

$ python TCPServer.py
127.0.0.1 wrote:
b'hello world with TCP'
127.0.0.1 wrote:
b'python is nice'

client :

$ python TCPClient.py hello world with TCP
Sent: hello world with TCP
Received: HELLO WORLD WITH TCP
$ python TCPClient.py python is nice
Sent: python is nice
Received: PYTHON IS NICE

socketserver.UDPServer Example

This is the server side :

import socketserver
class MyUDPHandler(socketserver.BaseRequestHandler):
""" This class works with TCP The processor is similar , It's just self.request Is a containing data and Binary of client socket Because there is no connection , So I'm passing through sendto() When sending data , You need to specify the address of the target """
def handle(self):
data = self.request[0].strip()
socket = self.request[1]
print("{} wrote:".format(self.client_address[0]))
print(data)
socket.sendto(data.upper(), self.client_address)
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
with socketserver.UDPServer((HOST, PORT), MyUDPHandler) as server:
server.serve_forever()

This is the client :

import socket
import sys
HOST, PORT = "localhost", 9999
data = " ".join(sys.argv[1:])
# SOCK_DGRAM It represents the use of UDP Type socket 
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# As you can see , Nothing here connect() call ; UDP No connection .
# As a substitute , Data goes directly through sendto() Send to the recipient 
sock.sendto(bytes(data + "\n", "utf-8"), (HOST, PORT))
received = str(sock.recv(1024), "utf-8")
print("Sent: {}".format(data))
print("Received: {}".format(received))

The output of this example is the same as before TCP The same version of

Asynchronous mixed class example

To build an asynchronous processor , have access to ThreadingMixIn and ForkingMixIn class .
One ThreadingMixIn Example of a class :

import socket
import threading
import socketserver
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
data = str(self.request.recv(1024), 'ascii')
cur_thread = threading.current_thread()
response = bytes("{}: {}".format(cur_thread.name, data), 'ascii')
self.request.sendall(response)
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
def client(ip, port, message):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((ip, port))
sock.sendall(bytes(message, 'ascii'))
response = str(sock.recv(1024), 'ascii')
print("Received: {}".format(response))
if __name__ == "__main__":
# port 0 It means to select any unused port 
HOST, PORT = "localhost", 0
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
with server:
ip, port = server.server_address
# Start a thread for the server , This thread will open another thread for each request 
server_thread = threading.Thread(target=server.serve_forever)
# When the main thread terminates , Exit server 
server_thread.daemon = True
server_thread.start()
print("Server loop running in thread:", server_thread.name)
client(ip, port, "Hello World 1")
client(ip, port, "Hello World 2")
client(ip, port, "Hello World 3")
server.shutdown()

The output of the example should look like this :

$ python ThreadedTCPServer.py
Server loop running in thread: Thread-1
Received: Thread-2: Hello World 1
Received: Thread-3: Hello World 2
Received: Thread-4: Hello World 3

ForkingMixIn Class is used in a similar way , The only difference is that the server will spawn a process for each request . This only supports fork() Of POSIX Available under the platform .

About this translation

The original intention of translating this document is , The translator is an English scum , However, they are learning Python This module of , It's too slow to read English documents , It's not convenient to go back and review , So just write down the Chinese in the process of learning , It's convenient to come back later
This document is based on Python 3.9.5 Translation of official documents
Original address : socketserver
I just said , The translator is an English scum , Therefore, there will inevitably be errors in the translation process , The understanding of module functions may not be comprehensive , Please correct me , Thank you first , Worship !!


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved