python异步网络通信框架_python中的异步网络框架socketserver

本文介绍如何使用Python的SocketServer模块快速搭建异步服务程序,包括解决端口占用问题及多线程处理客户端请求的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

SocketServer是Python基础库中提供的高级应用库, 主要用来编写异步服务程序. 最近工作原因需要写虚拟的外围服务程序, 正好了解到了这个, 所以写篇文章记录一下使用心得

在python3中SocketServer模块被改名为了socketserver模块

一个小例子

从一个小例子开始讲起, 一个小型回显服务器

server.py

#_*_ coding: utf-8 _*_

import SocketServer

class FooHandler(SocketServer.BaseRequestHandler):

def handle(self):

# 'self.request'为客户端socket, 可以调用recv, send方法接收或发送数据

data = self.request.recv(30).strip()

print('From (%s:%s) msg:%s' % (self.client_address[0], self.client_address[1], data))

if __name__ == '__main__':

server = SocketServer.TCPServer(('127.0.0.1', 8000), FooHandler)

server.serve_forever()

运行python server.py后输出如下

10dd0c0ca00a1f757507f1a0ede66e46.png

输出结果

可以看到我们只使用了不到20行的代码便实现了一个小型的异步服务器

需要注意这个程序客户端发起一次数据后客户会话就会关闭

在实际实验中, 可能我们在启动服务程序的时候经常会发生以下异常, 大多数原因是因为服务程序结束后, listen_socket进入TIME_WAIT状态, 导致第二次启动的时候会提示端口已经被占用了

Traceback (most recent call last):

File "server.py", line 12, in

server = SocketServer.ThreadingTCPServer(('127.0.0.1', 8000), FooHandler)

File "/usr/lib/python2.7/SocketServer.py", line 417, in __init__

self.server_bind()

File "/usr/lib/python2.7/SocketServer.py", line 431, in server_bind

self.socket.bind(self.server_address)

File "/usr/lib/python2.7/socket.py", line 228, in meth

return getattr(self._sock,name)(*args)

socket.error: [Errno 98] Address already in use

了解了异常产生的原因后, 其实就可以找到对应的解决方法了. 将服务listen_socket的SO_REUSEADDR属性打开即可, 由于SocketServer并没有直接将listen_socket暴露出来, 所以可能不方便直接操作listen_socket, 但是官方提供了一种方法, 就是写一个继承SocketServer.TCPServer的子类, 然后将子类的allow_reuse_address设置为True

修改一下我们的程序server.py, 代码如下

#_*_ coding: utf-8 _*_

import SocketServer

class FooHandler(SocketServer.BaseRequestHandler):

def handle(self):

# 'self.request'为客户端socket, 可以调用recv, send方法接收或发送数据

data = self.request.recv(30).strip()

print('From (%s:%s) msg:%s' % (self.client_address[0], self.client_address[1], data))

class SimpleServer(SocketServer.TCPServer):

# 开启监听套接字的SO_REUSEADDR属性, 此属性在'SocketServer.TCPServer'中是默认关闭的

allow_reuse_address = True

if __name__ == '__main__':

server = SimpleServer(('127.0.0.1', 8000), FooHandler)

server.serve_forever()

SocketServer.BaseRequestHandler一共有三个方法可以override

setup 处理前回调, 用于给连接socket设置一些必要的属性, 比如socket.setblocking(0)

handle 处理时回调, 定义服务器与客户端交互的逻辑

finish 处理后回调, 用于定义关闭连接后的清理操作

ThreadingTCPServer

之前例子中编写的服务器程序只能用于同时处理一个连接, 当使用多个客户一起连接时会发现后续的客户端会被阻塞住, 如果想要处理多个客户请求时, 需要使用到SocketServer.ThreadingTCPServer

thread_server.py

import SocketServer

class FooHandler(SocketServer.BaseRequestHandler):

def handle(self):

# 'self.request'为客户端socket, 可以调用recv, send方法接收或发送数据

data = self.request.recv(30).strip()

print('From (%s:%s) msg:%s' % (self.client_address[0], self.client_address[1], data))

if __name__ == '__main__':

server = ThreadingTCPServer(('127.0.0.1', 8000), FooHandler)

server.serve_forever()

如果喜欢我的文章点赞关注下哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值