目录
一、概述
socket
并不能多并发,只能支持一个用户,socketserver
模块是 Python 中用于创建网络服务器的模块,提供了一种简单而一致的接口。它是构建网络服务器的框架,处理了创建、维护和关闭连接的许多底层细节,socketserver
是socket
的再封装。
socketserver
在python2
中为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 服务器。
ForkingMixIn和
TCPServer`组合。 -
ForkingUDPServer
:每个请求创建一个新进程的UDP
服务器。ForkingMixIn
和UDPServer
组合。 -
ThreadingTCPServer
:在单独的线程中处理每个请求的 TCP 服务器。ThreadingMixIn
和TCPServer
组合。 -
ThreadingUDPServer
:在单独的线程中处理每个请求的 UDP 服务器。ThreadingMixIn
和UDPServer
组合。 -
BaseRequestHandler
:用于定制Handler类型,自定义的Handler类型只要继承自BaseRequestHandler,并覆盖写入它的handle() 方法即可。 -
StreamRequestHandler
:TCP请求处理类的一个实现。 -
DataStreamRequestHandler
:UDP请求处理类的一个实现。
server类继承关系:
请求处理类继承关系:
Socket
编程可以参考我这篇文章:Python 高级编程之网络编程 Socket(六)
二、socket 模块与 socketserver 关系
socket
和 socketserver
是两个不同的 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 讲解就先到这里,这里知识讲概念和示例,后面会有相关项目应用,有任何疑问欢迎给我留言哦,后续会持续更新相关技术文章,请小伙伴耐心等待哦,也可以关注我的公众号【大数据与云原生技术分享】进行深入技术交流~
标签:SocketServer,socketserver,Python,创建,self,编程,server,服务器,客户端 From: https://www.cnblogs.com/liugp/p/17118283.html