一、概述

socket不能多并发,只能支撑一个用户socketserver 模块是 Python 中用于创立网络服务器的模块,供给了一种简略而一致的接口。它是构建网络服务器的结构,处理了创立、维护和封闭衔接的许多底层细节,socketserversocket的再封装

  • socketserverpython2中为SocketServer
  • python3种取消了首字母大写,改名为socketserver
  • socketserver中包括了两种类,
    • 一种为服务类(server class):前者供给了许多办法:像绑定,监听,运行…… (也便是建立衔接的进程) 。
    • 一种为恳求处理类(request handle class):专心于如何处理用户所发送的数据(也便是业务逻辑)。
  • 一般情况下,一切的服务,都是先建立衔接,也便是建立一个服务类的实例,然后开始处理用户恳求,也便是建立一个恳求处理类的实例。

socketserver 模块供给了几个类,包括:

  • BaseServer:完成服务器的基本类。

  • TCPServer:处理 TCP 衔接的服务器。

  • UDPServer:处理 UDP 衔接的服务器。

  • UnixStreamServer:类似于TCPServer供给面向数据流的套接字衔接,可是旨在UNIX平台上可用。

  • UnixDatagramServer:类似于UDPServer供给面向数据报的套接字衔接,可是旨在UNIX平台上可用。

  • ForkingMixIn:完成了中心的进程化功用,用于与服务器类进行混合,供给异步特性。

  • ThreadingMixIn:完成了中心的线程化功用,用于与服务器类进行混合,异步特性。

  • ForkingTCPServer:每个恳求创立一个新进程的 TCP 服务器。ForkingMixInTCPServer`组合。

  • ForkingUDPServer:每个恳求创立一个新进程的 UDP 服务器。ForkingMixInUDPServer组合。

  • ThreadingTCPServer:在独自的线程中处理每个恳求的 TCP 服务器。ThreadingMixInTCPServer组合。

  • ThreadingUDPServer:在独自的线程中处理每个恳求的 UDP 服务器。ThreadingMixInUDPServer组合。

  • BaseRequestHandler:用于定制Handler类型,自定义的Handler类型只需承继自BaseRequestHandler,并覆盖写入它的handle() 办法即可。

  • StreamRequestHandler:TCP恳求处理类的一个完成。

  • DataStreamRequestHandler:UDP恳求处理类的一个完成。

server类承继联系:

Python 高级编程之网络编程 SocketServer(七)

恳求处理类承继联系:

Python 高级编程之网络编程 SocketServer(七)

Socket 编程能够参阅我这篇文章:Python 高档编程之网络编程 Socket(六)

Python 高级编程之网络编程 SocketServer(七)

二、socket 模块与 socketserver 联系

socketsocketserver 是两个不同的 Python 模块,都用于网络编程。

  • socket 模块供给了通用的套接字编程接口,可用于创立客户端和服务器端程序。它涵盖了与网络通信相关的底层细节,如创立套接字、绑定地址、监听恳求、接受衔接、发送数据和接收数据。
  • socketserver 模块是 socket 模块的一个封装,它笼统了服务器端网络编程的复杂度,使您能够快速编写服务器端程序。它供给了多种服务器类型,如多线程服务器多进程服务器单进程服务器,以满意不同的网络编程需求。此外,它还供给了简略的面向对象编程模型,答应您扩展基础类并定制服务器行为。

总而言之,假如您需求快速编写简略的服务器端程序,那么 socketserver 模块可能是您的最佳挑选;假如您需求更多的灵活性和细节控制,则能够运用 socket 模块。

在解析socketserver是如作业之前,咱们先看看socektserver类的承继联系图:

三、socketserver 模块运用

承继联系图中有五个类,其中四个类表示四种类型的同步服务器:

+------------+
| BaseServer |
+------------+
      |
      v
+-----------+        +------------------+
| TCPServer |------->| UnixStreamServer |
+-----------+        +------------------+
      |
      v
+-----------+        +--------------------+
| UDPServer |------->| UnixDatagramServer |
+-----------+        +--------------------+

1)创立 TCPServer

TCPServer 类是 Python3 中根据 TCP 协议的多线程服务器类

语法规矩:

# 这将运用InternetTCP协议,该协议供给客户机和服务器之间的连续数据流。假如 bind_and_activate 为true,构造函数主动测验调用 server_bind() 和 server_activate() . 其他参数将传递给 BaseServer 基类。
s = socketserver.TCPServer(server_address, RequestHandlerClass, bind_and_activate=True)
# socketserver.UnixStreamServer:仅限于Unix体系的,Unix套接字流
s = socketserver.UnixStreamServer(server_address, RequestHandlerClass, bind_and_activate=True)

运用 UDPServer 类时,您能够指定下列三个参数:

  • server_address:服务器的地址,他应该是一个元组包括地址和端口如:(“localhost”, 9000)。

  • RequestHandlerClass:咱们自定义的类,类中有必要重写handle()办法。用于处理一切socket恳求。

  • bind_and_activate:假如为True,将主动调用server_bind()和server_activate()。一般默许即可。

下面是一个运用 TCPServer 类的简略示例:

import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        # 接收客户端恳求的数据
        self.data = self.request.recv(1024).strip()
        print("{} 发送了:{}".format(self.client_address[0], self.data))
        # 向客户端发送呼应数据
        self.request.sendall(self.data.upper())
if __name__ == "__main__":
    # 创立服务器,绑定 IP 地址和端口号
    HOST, PORT = "localhost", 9999
    server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
    # 发动服务器
    server.serve_forever()

该代码定义了一个简略的多线程服务器,它绑定在本地主机(localhost)的端口号 9999 上。当有客户端衔接时,服务器会接收客户端发送的数据,然后将数据转换为大写并发送回客户端。

  • 请留意,您需求创立一个名为 MyTCPHandler 的处理程序类,该类有必要从 socketserver.BaseRequestHandler 类承继,并完成 handle 办法。在 handle 办法中,您能够处理客户端恳求,并向客户端发送呼应数据。

  • 最终,您能够经过调用 server.serve_forever() 办法发动服务器,并使其处于继续监听状况。

2)创立 UDPServer

UDPServer 是 socketserver 模块中用于创立 UDP 服务器的类。

语法规矩:

# 它运用数据报,这些数据报是离散的信息包,在传输进程中可能呈现无序到达或丢掉。
s = socketserver.UDPServer(server_address, RequestHandlerClass, bind_and_activate=True)
# socketserver.UnixDatagramServer:仅限于Unix体系的,Unix套接字流
s = socketserver.UnixDatagramServer(server_address, RequestHandlerClass, bind_and_activate=True)

运用 UDPServer 类时,您能够指定下列三个参数:

  • server_address:服务器的 IP 地址和端口号。例如:(“localhost”, 9999)。

  • RequestHandlerClass:处理客户端恳求的处理程序类。例如:MyUDPHandler。

  • bind_and_activate:假如为True,将主动调用server_bind()和server_activate()。一般默许即可。

四、异步服务器类(对线程、多进程)

socketserver 模块中也供给了一些异步服务器类,它们能够在独自的线程中处理多个客户端恳求,然后提高服务器的并发功能。下面一一介绍。

1)ThreadingMixIn(多线程)

ThreadingMixIn 类是 socketserver 模块中的一个异步服务器类,用于创立根据多线程的异步服务器

您能够经过承继该类来创立自己的异步服务器类,然后经过该类创立服务器。例如,创立一个根据多线程的异步 TCP 服务器的代码如下:

import socketserver
class ThreadingTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass
# 创立服务器,绑定 IP 地址和端口号
HOST, PORT = "localhost", 9999
server = ThreadingTCPServer((HOST, PORT), MyTCPHandler)

在这儿,您需求创立一个名为 MyTCPHandler 的处理程序类,该类有必要从 socketserver.BaseRequestHandler 类承继,并完成 handle 办法。该办法是处理客户端恳求的中心办法,在该办法中您能够处理客户端恳求,并向客户端发送呼应数据。

在创立根据多线程的异步服务器时,每个客户端恳求都会在一个独自的线程中处理,然后提高服务器的并发功能。

完好实例如下:

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 means to select an arbitrary unused port
    HOST, PORT = "localhost", 0
    server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
    with server:
        ip, port = server.server_address
        # Start a thread with the server -- that thread will then start one
        # more thread for each request
        server_thread = threading.Thread(target=server.serve_forever)
        # Exit the server thread when the main thread terminates
        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()

输出:

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

2)ForkingMixIn(多进程)

ForkingMixIn 类是 socketserver 模块中的一个异步服务器类,用于创立根据多进程的异步服务器。

您能够经过承继该类来创立自己的异步服务器类,然后经过该类创立服务器。例如,创立一个根据多进程的异步 TCP 服务器的代码如下:

import socketserver
class ForkingTCPServer(socketserver.ForkingMixIn, socketserver.TCPServer):
    pass
# 创立服务器,绑定 IP 地址和端口号
HOST, PORT = "localhost", 9999
server = ForkingTCPServer((HOST, PORT), MyTCPHandler)

在这儿,您需求创立一个名为 MyTCPHandler 的处理程序类,该类有必要从 socketserver.BaseRequestHandler 类承继,并完成 handle 办法。该办法是处理客户端恳求的中心办法,在该办法中您能够处理客户端恳求,并向客户端发送呼应数据。

在创立根据多进程的异步服务器时,每个客户端恳求都会在一个独自的进程中处理,然后提高服务器的并发功能。

【留意】在 Unix 体系上,运用多进程的异步服务器可能会导致内存占用添加。因此,在 Unix 体系上,建议运用多线程的异步服务器。

3)ForkingTCPServer (TCP 多进程)

ForkingTCPServer 是 socketserver 模块中的一个异步服务器类,用于创立根据多进程的 TCP 服务器。

要运用 ForkingTCPServer 类,您需求供给服务器的 IP 地址和端口号,以及处理客户端恳求的处理程序类。

以下是一个运用 ForkingTCPServer 类的示例:

import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        # 获取客户端恳求的数据
        data = self.request.recv(1024).strip()
        # 向客户端发送呼应数据
        self.request.sendall(bytes("Hello, {0}".format(data), "utf-8"))
# 创立服务器,绑定 IP 地址和端口号
HOST, PORT = "localhost", 9999
server = socketserver.ForkingTCPServer((HOST, PORT), MyTCPHandler)
# 发动服务器
server.serve_forever()

在这个示例中,咱们创立了一个名为 MyTCPHandler 的处理程序类,该类从 socketserver.BaseRequestHandler 类承继,并完成了 handle 办法。该办法是处理客户端恳求的中心办法,在该办法中您能够处理客户端恳求,并向客户端发送呼应数据。

接下来,咱们运用 socketserver.ForkingTCPServer 类创立了一个 TCP 服务器,并绑定了服务器的 IP 地址和端口号。最终,咱们运用 serve_forever 办法发动服务器,以便处理。

4)ForkingUDPServer (UDP 多进程)

ForkingUDPServer 是 socketserver 模块中的一个异步服务器类,用于创立根据多进程的 UDP 服务器。

要运用 ForkingUDPServer 类,您需求供给服务器的 IP 地址和端口号,以及处理客户端恳求的处理程序类。

以下是一个运用 ForkingUDPServer 类的示例:

import socketserver
class MyUDPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        data = self.request[0].strip()
        socket = self.request[1]
        # 向客户端发送呼应数据
        socket.sendto(bytes("Hello, {0}".format(data), "utf-8"), self.client_address)
# 创立服务器,绑定 IP 地址和端口号
HOST, PORT = "localhost", 9999
server = socketserver.ForkingUDPServer((HOST, PORT), MyUDPHandler)
# 发动服务器
server.serve_forever()

在这个示例中,咱们创立了一个名为 MyUDPHandler 的处理程序类,该类从 socketserver.BaseRequestHandler 类承继,并完成了 handle 办法。该办法是处理客户端恳求的中心办法,在该办法中您能够处理客户端恳求,并向客户端发送呼应数据。

接下来,咱们运用 socketserver.ForkingUDPServer 类创立了一个 UDP 服务器,并绑定了服务器的 IP 地址和端口号。最终,咱们运用 serve_forever 办法发动服务器,以便处理客户端恳求。

5)ThreadingTCPServer(TCP 多线程)

ThreadingTCPServer 是 socketserver 模块中的一个异步服务器类,用于创立根据多线程的 TCP 服务器

要运用 ThreadingTCPServer 类,您需求供给服务器的 IP 地址和端口号,以及处理客户端恳求的处理程序类。

以下是一个运用 ThreadingTCPServer 类的示例:

import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        data = self.request.recv(1024).strip()
        # 向客户端发送呼应数据
        self.request.sendall(bytes("Hello, {0}".format(data), "utf-8"))
# 创立服务器,绑定 IP 地址和端口号
HOST, PORT = "localhost", 9999
server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)
# 发动服务器
server.serve_forever()

在这个示例中,咱们创立了一个名为 MyTCPHandler 的处理程序类,该类从 socketserver.BaseRequestHandler 类承继,并完成了 handle 办法。该办法是处理客户端恳求的中心办法,在该办法中您能够处理客户端恳求,并向客户端发送呼应数据。

接下来,咱们运用 socketserver.ThreadingTCPServer 类创立了一个 TCP 服务器,并绑定了服务器的 IP 地址和端口号。最终,咱们运用 serve_forever 办法发动服务器,以便处理客户端恳求。

5)ThreadingUDPServer(UDP 多线程)

ThreadingUDPServer 是 socketserver 模块中的一个异步服务器类,用于创立根据多线程的 UDP 服务器。

要运用 ThreadingUDPServer 类,您需求供给服务器的 IP 地址和端口号,以及处理客户端恳求的处理程序类。

以下是一个运用 ThreadingUDPServer 类的示例:

import socketserver
class MyUDPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        data = self.request[0].strip()
        socket = self.request[1]
        # 向客户端发送呼应数据
        socket.sendto(bytes("Hello, {0}".format(data), "utf-8"), self.client_address)
# 创立服务器,绑定 IP 地址和端口号
HOST, PORT = "localhost", 9999
server = socketserver.ThreadingUDPServer((HOST, PORT), MyUDPHandler)
# 发动服务器
server.serve_forever()

在这个示例中,咱们创立了一个名为 MyUDPHandler 的处理程序类,该类从 socketserver.BaseRequestHandler 类承继,并完成了 handle 办法。该办法是处理客户端恳求的中心办法,在该办法中您能够处理客户端恳求,并向客户端发送呼应数据。

接下来,咱们运用 socketserver.ThreadingUDPServer 类创立了一个 UDP 服务器,并绑定了服务器的 IP 地址和端口号。最终,咱们运用 serve_forever 办法发动服务器,以便处理客户端恳求。


Python 高档编程之网络编程 SocketServer 讲解就先到这儿,这儿知识讲概念和示例,后面会有相关项目使用,有任何疑问欢迎给我留言哦,后续会继续更新相关技术文章,请小伙伴耐心等待哦,也能够关注我的大众号【大数据与云原生技术分享】进行深入技术交流~

Python 高级编程之网络编程 SocketServer(七)