您的位置:

Python SocketServer详解

一、Python SocketServer概述

Python SocketServer是Python标准库中的一个模块,它提供了一个类似于socket的框架,使我们能够在Python中使用多种协议来创建网络服务器和客户端。

SocketServer可以支持多线程、多进程、单线程、异步I/O等多种方式。使用SocketServer模块可以更简单易行的实现复杂的网络编程,而不需要深入理解操作系统底层的网络实现。

二、SocketServer类及方法

Python SocketServer提供了四个主要的类,每个类具有不同的特色。

1. BaseServer:这是所有服务器类的基类,它仅提供框架结构,在派生类中实现具体的协议。

2. TCPServer:可以通过TCP协议在网络上提供服务的服务器。

3. UDPServer:使用UDP协议在网络上提供服务的服务器。

4. UnixStreamServer和UnixDatagramServer:在本地Unix域套接字上提供服务的服务器。

除此之外,SocketServer还提供了一些常用的方法,如handle_request、serve_forever、handle_error等,我们可以通过继承SocketServer类和重写这些方法来实现自己的服务器逻辑。


import SocketServer
class MyHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        self.request.send("hello world\n")
  
MyServer = SocketServer.TCPServer(('127.0.0.1', 8000), MyHandler)
MyServer.serve_forever()

三、TCP vs UDP

Python SocketServer模块中的TCP和UDP提供了两种协议来实现网络通讯。

TCP协议提供了数据包传输的可靠性,保证了数据传输的准确性。而UDP协议则不提供像TCP协议那样的可靠性,但传输速度更快,更符合实时性的需求。

使用Python SocketServer模块时,需要根据实际需要选择不同的协议。

四、多线程与多进程

在Python SocketServer中,我们可以通过多线程或多进程来实现并发请求处理。

多线程可以通过ThreadingMixIn类实现,多进程可以通过ForkingMixIn实现。具体来说,我们需要继承SocketServer类并混合ThreadingMixIn或ForkingMixIn,然后在重写handle方法时使用Python的thread模块或multiprocessing模块来启动新的进程或线程。


import SocketServer
import threading

class MyHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        data = str(self.request.recv(1024), 'ascii')
        cur_thread = threading.current_thread().name
        message = "{}: {}".format(cur_thread, data)
        print(message)
        response = bytes("{}\n".format(message), 'ascii')
        self.request.sendall(response)

class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    pass

server = ThreadedTCPServer(('localhost', 8000), MyHandler)
server.allow_reuse_address = True
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()

五、异步I/O

Python SocketServer也支持异步I/O,这是一种替代多线程和多进程的解决方案。它使用网络事件轮询,当有事件发生时,自动调用相应的回掉函数。

Python 3.4之后,标准库中引入了asyncio模块,使得异步I/O更加便捷。


import asyncio

class EchoServerProtocol(asyncio.Protocol):
    def connection_made(self, transport):
        self.transport = transport
    
    def data_received(self, data):
        message = data.decode()
        self.transport.write(data)

loop = asyncio.get_event_loop()
coro = loop.create_server(EchoServerProtocol, '127.0.0.1', 8000)
server = loop.run_until_complete(coro)

try:
    loop.run_forever()
except KeyboardInterrupt:
    pass

server.close()
loop.run_until_complete(server.wait_closed())
loop.close()