socketserver模块

一、socketserver模块说明

  • socket并不能多并发,只能支持一个用户,socketserver 简化了编写网络服务程序的任务,socketserver是socket的在封装。socketserver在python2中为SocketServer,在python3种取消了首字母大写,改名为socketserver。
  • socketserver内部使用IO多路复用以及“多线程”和“多进程”,从而实现并发处理多个客户端请求的scoket服务端。即,每个客户端请求连接到服务器时,socket服务端都会在服务器是创建一个“线程”或“进程”专门负责处理当前客户端的所有请求。
  • socketserver中包含了两种类,一种为服务类(server class),一种为请求处理类(request handle class)。前者提供了许多方法:像绑定,监听,运行…… (也就是建立连接的过程);后者则专注于如何处理用户所发送的数据(也就是事务逻辑)。一般情况下,所有的服务,都是先建立连接,也就是建立一个服务类的实例,然后开始处理用户请求,也就是建立一个请求处理类的实例。

二、server类型介绍

  1.5种server类 BaseServer,TCPServer,UnixStreamServer,UDPServer,UnixDatagramServer。 注意:BaseServer不直接对外服务。

  • class socketserver.BaseServer:这是模块中的所有服务器对象的超类。包含服务器的核心功能与混合类(min-in)的钩子功能.这个类主用于派生,不要直接生成这个类的类对象,它定义了接口,但是大多数的方法不实现,在子类中进行细化。
  • class socketserver.TCPServer(server_address, RequestHandlerClass, bind_and_activate=True)  支持使用IPV4的TCP协议的服务器,address是一个(host,port)元组.Handler是BaseRequestHandler或StreamRequestHandler类的子类的实例.
  • class socketserver.UDPServer(server_address, RequestHandlerClass, bind_and_activate=True)  支持使用IPV4的UDP协议的服务器,address和handler与TCPServer类似.
  • class socketserver.UnixStreamServer(server_address, RequestHandlerClass, bind_and_activate=True)  使用UNIX域套接字实现面向数据流协议的服务器,继承自TCPServer.
  • class socketserver.UnixDatagramServer(server_address, RequestHandlerClass,bind_and_activate=True)  使用UNIX域套接字实现数据报协议的服务器,继承自UDPServer.

 

  2.继承关系

  3.BaseServer方法

 1 BaseServer.fileno():返回服务器监听套接字的整数文件描述符。通常用来传递给select.select(), 以允许一个进程监视多个服务器。
 2 
 3 BaseServer.handle_request():处理单个请求。处理顺序:get_request(), verify_request(), process_request()。如果用户提供handle()方法抛出异常,将调用服务器的handle_error()方法。如果self.timeout内没有请求收到, 将调用handle_timeout()并返回handle_request()。
 4 
 5 BaseServer.serve_forever(poll_interval=0.5): 处理请求,直到一个明确的shutdown()请求。每poll_interval秒轮询一次shutdown。忽略self.timeout。如果你需要做周期性的任务,建议放置在其他线程。
 6 
 7 BaseServer.shutdown():告诉serve_forever()循环停止并等待其停止。python2.6版本。
 8 
 9 BaseServer.address_family: 地址家族,比如socket.AF_INET和socket.AF_UNIX。
10 
11 BaseServer.RequestHandlerClass:用户提供的请求处理类,这个类为每个请求创建实例。
12 
13 BaseServer.server_address:服务器侦听的地址。格式根据协议家族地址的各不相同,请参阅socket模块的文档。
14 
15 BaseServer.socketSocket:服务器上侦听传入的请求socket对象的服务器。
16 
17 服务器类支持下面的类变量:
18 
19 BaseServer.allow_reuse_address:服务器是否允许地址的重用。默认为false ,并且可在子类中更改。
20 
21 BaseServer.request_queue_size
22 
23 请求队列的大小。如果单个请求需要很长的时间来处理,服务器忙时请求被放置到队列中,最多可以放request_queue_size个。一旦队列已满,来自客户端的请求将得到 “Connection denied”错误。默认值通常为5 ,但可以被子类覆盖。
24 
25 BaseServer.socket_type:服务器使用的套接字类型; socket.SOCK_STREAM和socket.SOCK_DGRAM等。
26 
27 BaseServer.timeout:超时时间,以秒为单位,或 None表示没有超时。如果handle_request()在timeout内没有收到请求,将调用handle_timeout()。
28 
29 下面方法可以被子类重载,它们对服务器对象的外部用户没有影响。
30 
31 BaseServer.finish_request():实际处理RequestHandlerClass发起的请求并调用其handle()方法。 常用。
32 
33 BaseServer.get_request():接受socket请求,并返回二元组包含要用于与客户端通信的新socket对象,以及客户端的地址。
34 
35 BaseServer.handle_error(request, client_address):如果RequestHandlerClass的handle()方法抛出异常时调用。默认操作是打印traceback到标准输出,并继续处理其他请求。
36 
37 BaseServer.handle_timeout():超时处理。默认对于forking服务器是收集退出的子进程状态,threading服务器则什么都不做。
38 
39 BaseServer.process_request(request, client_address) :调用finish_request()创建RequestHandlerClass的实例。如果需要,此功能可以创建新的进程或线程来处理请求,ForkingMixIn和ThreadingMixIn类做到这点。常用。
40 
41 BaseServer.server_activate():通过服务器的构造函数来激活服务器。默认的行为只是监听服务器套接字。可重载。
42 
43 BaseServer.server_bind():通过服务器的构造函数中调用绑定socket到所需的地址。可重载。
44 
45 BaseServer.verify_request(request, client_address):返回一个布尔值,如果该值为True ,则该请求将被处理,反之请求将被拒绝。此功能可以重写来实现对服务器的访问控制。默认的实现始终返回True。client_address可以限定客户端,比如只处理指定ip区间的请求。 常用。
BaseServer方法

 

  1 class BaseServer:
  2 
  3     """Base class for server classes.
  4 
  5     Methods for the caller:
  6 
  7     - __init__(server_address, RequestHandlerClass)
  8     - serve_forever(poll_interval=0.5)
  9     - shutdown()
 10     - handle_request()  # if you do not use serve_forever()
 11     - fileno() -> int   # for selector
 12 
 13     Methods that may be overridden:
 14 
 15     - server_bind()
 16     - server_activate()
 17     - get_request() -> request, client_address
 18     - handle_timeout()
 19     - verify_request(request, client_address)
 20     - server_close()
 21     - process_request(request, client_address)
 22     - shutdown_request(request)
 23     - close_request(request)
 24     - service_actions()
 25     - handle_error()
 26 
 27     Methods for derived classes:
 28 
 29     - finish_request(request, client_address)
 30 
 31     Class variables that may be overridden by derived classes or
 32     instances:
 33 
 34     - timeout
 35     - address_family
 36     - socket_type
 37     - allow_reuse_address
 38 
 39     Instance variables:
 40 
 41     - RequestHandlerClass
 42     - socket
 43 
 44     """
 45 
 46     timeout = None
 47 
 48     def __init__(self, server_address, RequestHandlerClass):
 49         """Constructor.  May be extended, do not override."""
 50         self.server_address = server_address
 51         self.RequestHandlerClass = RequestHandlerClass
 52         self.__is_shut_down = threading.Event()
 53         self.__shutdown_request = False
 54 
 55     def server_activate(self):
 56         """Called by constructor to activate the server.
 57 
 58         May be overridden.
 59 
 60         """
 61         pass
 62 
 63     def serve_forever(self, poll_interval=0.5):
 64         """Handle one request at a time until shutdown.
 65 
 66         Polls for shutdown every poll_interval seconds. Ignores
 67         self.timeout. If you need to do periodic tasks, do them in
 68         another thread.
 69         """
 70         self.__is_shut_down.clear()
 71         try:
 72             # XXX: Consider using another file descriptor or connecting to the
 73             # socket to wake this up instead of polling. Polling reduces our
 74             # responsiveness to a shutdown request and wastes cpu at all other
 75             # times.
 76             with _ServerSelector() as selector:
 77                 selector.register(self, selectors.EVENT_READ)
 78 
 79                 while not self.__shutdown_request:
 80                     ready = selector.select(poll_interval)
 81                     if ready:
 82                         self._handle_request_noblock()
 83 
 84                     self.service_actions()
 85         finally:
 86             self.__shutdown_request = False
 87             self.__is_shut_down.set()
 88 
 89     def shutdown(self):
 90         """Stops the serve_forever loop.
 91 
 92         Blocks until the loop has finished. This must be called while
 93         serve_forever() is running in another thread, or it will
 94         deadlock.
 95         """
 96         self.__shutdown_request = True
 97         self.__is_shut_down.wait()
 98 
 99     def service_actions(self):
100         """Called by the serve_forever() loop.
101 
102         May be overridden by a subclass / Mixin to implement any code that
103         needs to be run during the loop.
104         """
105         pass
106 
107     # The distinction between handling, getting, processing and finishing a
108     # request is fairly arbitrary.  Remember:
109     #
110     # - handle_request() is the top-level call.  It calls selector.select(),
111     #   get_request(), verify_request() and process_request()
112     # - get_request() is different for stream or datagram sockets
113     # - process_request() is the place that may fork a new process or create a
114     #   new thread to finish the request
115     # - finish_request() instantiates the request handler class; this
116     #   constructor will handle the request all by itself
117 
118     def handle_request(self):
119         """Handle one request, possibly blocking.
120 
121         Respects self.timeout.
122         """
123         # Support people who used socket.settimeout() to escape
124         # handle_request before self.timeout was available.
125         timeout = self.socket.gettimeout()
126         if timeout is None:
127             timeout = self.timeout
128         elif self.timeout is not None:
129             timeout = min(timeout, self.timeout)
130         if timeout is not None:
131             deadline = time() + timeout
132 
133         # Wait until a request arrives or the timeout expires - the loop is
134         # necessary to accommodate early wakeups due to EINTR.
135         with _ServerSelector() as selector:
136             selector.register(self, selectors.EVENT_READ)
137 
138             while True:
139                 ready = selector.select(timeout)
140                 if ready:
141                     return self._handle_request_noblock()
142                 else:
143                     if timeout is not None:
144                         timeout = deadline - time()
145                         if timeout < 0:
146                             return self.handle_timeout()
147 
148     def _handle_request_noblock(self):
149         """Handle one request, without blocking.
150 
151         I assume that selector.select() has returned that the socket is
152         readable before this function was called, so there should be no risk of
153         blocking in get_request().
154         """
155         try:
156             request, client_address = self.get_request()
157         except OSError:
158             return
159         if self.verify_request(request, client_address):
160             try:
161                 self.process_request(request, client_address)
162             except Exception:
163                 self.handle_error(request, client_address)
164                 self.shutdown_request(request)
165             except:
166                 self.shutdown_request(request)
167                 raise
168         else:
169             self.shutdown_request(request)
170 
171     def handle_timeout(self):
172         """Called if no new request arrives within self.timeout.
173 
174         Overridden by ForkingMixIn.
175         """
176         pass
177 
178     def verify_request(self, request, client_address):
179         """Verify the request.  May be overridden.
180 
181         Return True if we should proceed with this request.
182 
183         """
184         return True
185 
186     def process_request(self, request, client_address):
187         """Call finish_request.
188 
189         Overridden by ForkingMixIn and ThreadingMixIn.
190 
191         """
192         self.finish_request(request, client_address)
193         self.shutdown_request(request)
194 
195     def server_close(self):
196         """Called to clean-up the server.
197 
198         May be overridden.
199 
200         """
201         pass
202 
203     def finish_request(self, request, client_address):
204         """Finish one request by instantiating RequestHandlerClass."""
205         self.RequestHandlerClass(request, client_address, self)
206 
207     def shutdown_request(self, request):
208         """Called to shutdown and close an individual request."""
209         self.close_request(request)
210 
211     def close_request(self, request):
212         """Called to clean up an individual request."""
213         pass
214 
215     def handle_error(self, request, client_address):
216         """Handle an error gracefully.  May be overridden.
217 
218         The default is to print a traceback and continue.
219 
220         """
221         print('-'*40, file=sys.stderr)
222         print('Exception happened during processing of request from',
223             client_address, file=sys.stderr)
224         import traceback
225         traceback.print_exc()
226         print('-'*40, file=sys.stderr)
227 
228     def __enter__(self):
229         return self
230 
231     def __exit__(self, *args):
232         self.server_close()
BaseServer源码

 

  4.TCPServer方法

  • server_bind
  • server_activate
  • server_close
  • fileno
  • get_request
  • shutdown_request
  • close_request
  1 class TCPServer(BaseServer):
  2 
  3     """Base class for various socket-based server classes.
  4 
  5     Defaults to synchronous IP stream (i.e., TCP).
  6 
  7     Methods for the caller:
  8 
  9     - __init__(server_address, RequestHandlerClass, bind_and_activate=True)
 10     - serve_forever(poll_interval=0.5)
 11     - shutdown()
 12     - handle_request()  # if you don't use serve_forever()
 13     - fileno() -> int   # for selector
 14 
 15     Methods that may be overridden:
 16 
 17     - server_bind()
 18     - server_activate()
 19     - get_request() -> request, client_address
 20     - handle_timeout()
 21     - verify_request(request, client_address)
 22     - process_request(request, client_address)
 23     - shutdown_request(request)
 24     - close_request(request)
 25     - handle_error()
 26 
 27     Methods for derived classes:
 28 
 29     - finish_request(request, client_address)
 30 
 31     Class variables that may be overridden by derived classes or
 32     instances:
 33 
 34     - timeout
 35     - address_family
 36     - socket_type
 37     - request_queue_size (only for stream sockets)
 38     - allow_reuse_address
 39 
 40     Instance variables:
 41 
 42     - server_address
 43     - RequestHandlerClass
 44     - socket
 45 
 46     """
 47 
 48     address_family = socket.AF_INET
 49 
 50     socket_type = socket.SOCK_STREAM
 51 
 52     request_queue_size = 5
 53 
 54     allow_reuse_address = False
 55 
 56     def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
 57         """Constructor.  May be extended, do not override."""
 58         BaseServer.__init__(self, server_address, RequestHandlerClass)
 59         self.socket = socket.socket(self.address_family,
 60                                     self.socket_type)
 61         if bind_and_activate:
 62             try:
 63                 self.server_bind()
 64                 self.server_activate()
 65             except:
 66                 self.server_close()
 67                 raise
 68 
 69     def server_bind(self):
 70         """Called by constructor to bind the socket.
 71 
 72         May be overridden.
 73 
 74         """
 75         if self.allow_reuse_address:
 76             self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 77         self.socket.bind(self.server_address)
 78         self.server_address = self.socket.getsockname()
 79 
 80     def server_activate(self):
 81         """Called by constructor to activate the server.
 82 
 83         May be overridden.
 84 
 85         """
 86         self.socket.listen(self.request_queue_size)
 87 
 88     def server_close(self):
 89         """Called to clean-up the server.
 90 
 91         May be overridden.
 92 
 93         """
 94         self.socket.close()
 95 
 96     def fileno(self):
 97         """Return socket file number.
 98 
 99         Interface required by selector.
100 
101         """
102         return self.socket.fileno()
103 
104     def get_request(self):
105         """Get the request and client address from the socket.
106 
107         May be overridden.
108 
109         """
110         return self.socket.accept()
111 
112     def shutdown_request(self, request):
113         """Called to shutdown and close an individual request."""
114         try:
115             #explicitly shutdown.  socket.close() merely releases
116             #the socket and waits for GC to perform the actual close.
117             request.shutdown(socket.SHUT_WR)
118         except OSError:
119             pass #some platforms may raise ENOTCONN here
120         self.close_request(request)
121 
122     def close_request(self, request):
123         """Called to clean up an individual request."""
124         request.close()
TCPServer源码

  5.UDPServer方法

  • get_request
  • server_activate
  • shutdown_request
  • close_request
 1 class UDPServer(TCPServer):
 2 
 3     """UDP server class."""
 4 
 5     allow_reuse_address = False
 6 
 7     socket_type = socket.SOCK_DGRAM
 8 
 9     max_packet_size = 8192
10 
11     def get_request(self):
12         data, client_addr = self.socket.recvfrom(self.max_packet_size)
13         return (data, self.socket), client_addr
14 
15     def server_activate(self):
16         # No need to call listen() for UDP.
17         pass
18 
19     def shutdown_request(self, request):
20         # No need to shutdown anything.
21         self.close_request(request)
22 
23     def close_request(self, request):
24         # No need to close anything.
25         pass
UDPServer源码

 

三、request类(request handle class)

  1.request类

  • class BaseRequestHandler
  • class StreamRequestHandler(BaseRequestHandler)
  • class DatagramRequestHandler(BaseRequestHandler)

  

  BaseRequestHandle类的实例化可以实现以下方法:

  • sock.handle()调用该方法执行实际的请求操作.调用函数可以不带任何参数,但是几个实例变量包含有用的值.sock.request包含请求,sock.client_address包含客户端的地址,sock.server包含调用处理程序的实例.对于TCP之类的数据流服务,sock.request属性是套接字对象.

  • 对于数据报服务,还是包含收到数据的字节字符串.
  • sock.setup()该方法在handle()之前调用.默认情况下,不执行任何操作.如果希望服务器实现更多连接设置(如建立SSL连接),则无需调用该方法.

  • sock.finish()调用本方法可以在执行完handle()之后执行清除操作.默认情况下,不执行任何操作.如果setup()和handle()方法都不生成异常,则无需调用该方法.

  • 如果知道应用程序只能操纵面向数据流的连接(如TCP),那么应从StreamRequestHandle继承,而不是BaseRequestHandler.StreaRequestHandler类设置了两个属性,sock.wfile是将数据写入客户端的类文件对象,sock.rfile是从客户端读取数据的类文件对象.
  • 如果编写针对数据包操作的处理程序并将响应持续返回给发送方,那么它应当从DategramRequestHandler继承.它提供的类接口与StreamREquestHandler相同.

 

  2.继承图

  

  3.源码

 1 class BaseRequestHandler:
 2 
 3     """Base class for request handler classes.
 4 
 5     This class is instantiated for each request to be handled.  The
 6     constructor sets the instance variables request, client_address
 7     and server, and then calls the handle() method.  To implement a
 8     specific service, all you need to do is to derive a class which
 9     defines a handle() method.
10 
11     The handle() method can find the request as self.request, the
12     client address as self.client_address, and the server (in case it
13     needs access to per-server information) as self.server.  Since a
14     separate instance is created for each request, the handle() method
15     can define other arbitrary instance variables.
16 
17     """
18 
19     def __init__(self, request, client_address, server):
20         self.request = request
21         self.client_address = client_address
22         self.server = server
23         self.setup()
24         try:
25             self.handle()
26         finally:
27             self.finish()
28 
29     def setup(self):
30         pass
31 
32     def handle(self):
33         pass
34 
35     def finish(self):
36         pass
37 
38 
39 # The following two classes make it possible to use the same service
40 # class for stream or datagram servers.
41 # Each class sets up these instance variables:
42 # - rfile: a file object from which receives the request is read
43 # - wfile: a file object to which the reply is written
44 # When the handle() method returns, wfile is flushed properly
BaseRequestHandler源码
 1 class StreamRequestHandler(BaseRequestHandler):
 2 
 3     """Define self.rfile and self.wfile for stream sockets."""
 4 
 5     # Default buffer sizes for rfile, wfile.
 6     # We default rfile to buffered because otherwise it could be
 7     # really slow for large data (a getc() call per byte); we make
 8     # wfile unbuffered because (a) often after a write() we want to
 9     # read and we need to flush the line; (b) big writes to unbuffered
10     # files are typically optimized by stdio even when big reads
11     # aren't.
12     rbufsize = -1
13     wbufsize = 0
14 
15     # A timeout to apply to the request socket, if not None.
16     timeout = None
17 
18     # Disable nagle algorithm for this socket, if True.
19     # Use only when wbufsize != 0, to avoid small packets.
20     disable_nagle_algorithm = False
21 
22     def setup(self):
23         self.connection = self.request
24         if self.timeout is not None:
25             self.connection.settimeout(self.timeout)
26         if self.disable_nagle_algorithm:
27             self.connection.setsockopt(socket.IPPROTO_TCP,
28                                        socket.TCP_NODELAY, True)
29         self.rfile = self.connection.makefile('rb', self.rbufsize)
30         if self.wbufsize == 0:
31             self.wfile = _SocketWriter(self.connection)
32         else:
33             self.wfile = self.connection.makefile('wb', self.wbufsize)
34 
35     def finish(self):
36         if not self.wfile.closed:
37             try:
38                 self.wfile.flush()
39             except socket.error:
40                 # A final socket error may have occurred here, such as
41                 # the local error ECONNABORTED.
42                 pass
43         self.wfile.close()
44         self.rfile.close()
StreamRequestHandler源码
 1 class DatagramRequestHandler(BaseRequestHandler):
 2 
 3     """Define self.rfile and self.wfile for datagram sockets."""
 4 
 5     def setup(self):
 6         from io import BytesIO
 7         self.packet, self.socket = self.request
 8         self.rfile = BytesIO(self.packet)
 9         self.wfile = BytesIO()
10 
11     def finish(self):
12         self.socket.sendto(self.wfile.getvalue(), self.client_address)
DatagramRequestHandler源码

 

四、线程与进程类

  • ForkingMinIn  实现了核心的进程化功能,用于与服务器类进行混合(min-in),以提供一些异步特性.不要直接生成这个类的对象
  • ThreadingMinIn  实现了核心的线程化功能,用于与服务器类进行混合(min-in),以提供一些异步特性,不要直接生成这个类的对象
  • ForkingTCPServer  ForkingMinIn与TCPServer的组合
  • ForkingUDPServer  ForkingMinIn与UDPServer的组合

 

五、server类和request类关系与继承

 

 

 

 

 说明:

六、TCPServer 实例

  1.创建一个server需要的几个步骤:

  原文:

  • First, you must create a request handler class by subclassing the BaseRequestHandlerclass and overriding its handle() method; this method will process incoming requests. 
  • Second, you must instantiate one of the server classes, passing it the server’s address and the request handler class.
  • Then call the handle_request() or serve_forever() method of the server object to process one or many requests.
  • Finally, call server_close() to close the socket.

  

  翻译:

  • 首先,您必须创建一个请求处理类的子类 继承BaseRequestHandlerclass,并重写父类里的handle()方法,该方法将处理传入的请求。
  • 其次,你必须实例化一个服务器的类,并且传递服务器的地址,端口和上面一步创建的类名。
  • 然后调用handle_request()或者serve_forever()方法来处理一个或多个请求。handle_request()只处理一个请求,serve_forever()处理多个请求,永远执行。
  • 最后,调用server_close()关闭套接字。

  

  2.实例1

  

import socketserver

class MyTCPHandler(socketserver.BaseRequestHandler): #服务类,监听绑定等等
    """
    The request handler class for our server.

    It is instantiated once per connection to the server, and must
    override the handle() method to implement communication to the
    client.
    """
 
    def handle(self):  #请求处理类,所有请求的交互都是在handle里执行的
        # self.request is the TCP socket connected to the client
        self.data = self.request.recv(1024).strip()#每一个请求都会实例化MyTCPHandler(socketserver.BaseRequestHandler):
        print("{} wrote:".format(self.client_address[0]))
        print(self.data)
        # just send back the same data, but upper-cased       
        self.request.sendall(self.data.upper())#sendall是重复调用send.

if __name__ == "__main__":
    HOST, PORT = "localhost", 9999

    # Create the server, binding to localhost on port 9999
    server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)

    # Activate the server; this will keep running until you
    # interrupt the program with Ctrl-C
    server.serve_forever()
 
 server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)   #线程
# server  = socketserver.ForkingTCPServer((HOST, PORT), MyTCPHandler) #多进程 linux适用
# server = socketserver.TCPServer((HOST, PORT), MyTCPHandler) 单进程

  

  3.实例2

  Server端:

import socketserver

class Myserver(socketserver.BaseRequestHandler):
    def handle(self):  #self.request 就相当于一个 conn
        print(self.request.recv(1024).decode('utf-8'))

if __name__ == '__main__':
    server = socketserver.ThreadingTCPServer(('127.0.0.1',8080),Myserver)
    server.serve_forever()

  Client端:

import socket

sk = socket.socket()
sk.connect(('127.0.0.1',8080))
sk.send('人生苦短,请用Python!'.encode('utf-8'))
sk.close()

  执行结果:

人生苦短,请用Python!

 

 

查找属性的顺序:ThreadingTCPServer->ThreadingMixIn->TCPServer->BaseServer

  • 实例化得到ftpserver,先找类ThreadingTCPServer的__init__,在TCPServer中找到,进而执行server_bind,server_active
  • 找ftpserver下的serve_forever,在BaseServer中找到,进而执行self._handle_request_noblock(),该方法同样是在BaseServer中
  • 执行self._handle_request_noblock()进而执行request, client_address = self.get_request()(就是TCPServer中的self.socket.accept()),然后执行self.process_request(request, client_address)
  • 在ThreadingMixIn中找到process_request,开启多线程应对并发,进而执行process_request_thread,执行self.finish_request(request, client_address)
  • 上述四部分完成了链接循环,本部分开始进入处理通讯部分,在BaseServer中找到finish_request,触发我们自己定义的类的实例化,去找__init__方法,而我们自己定义的类没有该方法,则去它的父类也就是BaseRequestHandler中

 

七、UDPServer 实例

  server:

 

import socketserver

class MyUDPHandler(socketserver.BaseRequestHandler):
    """
    This class works similar to the TCP handler class, except that
    self.request consists of a pair of data and client socket, and since
    there is no connection the client address must be given explicitly
    when sending data back via sendto().
    """

    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()

  

  client:

import socket
import sys

HOST, PORT = "localhost", 9999
data = " ".join(sys.argv[1:])

# SOCK_DGRAM is the socket type to use for UDP sockets
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# As you can see, there is no connect() call; UDP has no connections.
# Instead, data is directly sent to the recipient via sendto().
sock.sendto(bytes(data + "\n", "utf-8"), (HOST, PORT))
received = str(sock.recv(1024), "utf-8")

print("Sent:     {}".format(data))
print("Received: {}".format(received))

  

 

posted @ 2018-10-30 10:03  %华&仔%  阅读(540)  评论(0编辑  收藏  举报