Python网络与并发编程 17 常见I/O示例演示

本文介绍了Python中从阻塞I/O到异步I/O的网络编程,包括socket服务端的阻塞、非阻塞、I/O多路复用和异步实现,探讨了epoll在同步与异步之间的角色,并讨论了如何通过多线程、异步框架提升性能。
摘要由CSDN通过智能技术生成

阻塞I/O的socket服务端

使用socket模块与concurrent.futures实现阻塞式I/O的socket服务端。

开启多个子线程,每个子线程单独负责一个链接,这意味着该服务器最大的并发量取决于你CPU能够打开的最大有效线程数:

import socket
import threading
import concurrent.futures


class TcpServer:
    def __init__(self, bind_addr=("localhost", 8001), allow_reuse_address=False):

        self.socket = socket.socket()
        self.backlog = 5
        self.bufsize = 1024
        self.server_addr = bind_addr
        self.allow_reuse_address = allow_reuse_address

        # 默认创建的线程数为cpu核心数 * 5
        self.executor = concurrent.futures.ThreadPoolExecutor()

    def run_server(self):
        """运行服务"""

        self.server_bind()
        self.server_activate()
        self.handle_request()

    def server_bind(self):
        """绑定地址"""

        if self.allow_reuse_address:
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        self.socket.bind(self.server_addr)

    def server_activate(self):
        """开启监听"""

        self.socket.listen(self.backlog)

    def handle_request(self):
        """处理链接"""

        while 1:
            # 阻塞点1:accept()函数会导致程序卡住,直至有新的链接请求到来
            conn, addr = self.socket.accept()
            self.executor.submit(
                self.handle_communicate, conn, addr)

    def handle_communicate(self, conn, addr):
        """多线程处理通信"""

        thName = threading.current_thread().name
        print(f"{addr} connect server, handle thread : {thName}")
        while 1:
            try:
                # 阻塞点2:recv()函数会导致程序卡住,直至有新的信息放入conn双向链接通道中
                data = conn.recv(self.bufsize)
                if not data:
                    raise Exception(
                        f"{addr} close connect, handle thread : {thName}")
                conn.send(data.upper())
            except Exception as e:
                self.close_connect(conn, e)
                break

    def close_connect(self, conn, msg):
        """关闭链接"""
        
        conn.close()
        print(msg)


if __name__ == "__main__":
    server = TcpServer(allow_reuse_address=True)
    server.run_server()

非阻塞I/O的socket服务端

将上述的socket服务端改为非阻塞的:

import socket
import threading
import concurrent.futures


class TcpServer:
    def __init__(self, bind_addr=("localhost", 8001), allow_reuse_address=False):
        
        self.socket = socket.socket()
        
        # 设置为非阻塞
        self.socket.setblocking(False)
        
        self.backlog = 5
        self.bufsize = 1024
        self.server_addr = bind_addr
        self.allow_reuse_address = allow_reuse_address
        
        # 默认创建的线程数为cpu核心数 * 5
        self.executor = concurrent.futures.ThreadPoolExecutor()

    def run_server(self):
        """运行服务"""
        
        self.server_bind()
        self.server_activate()
        self.handle_request()

    def server_bind(self):
        """绑定地址"""
        
        if self.allow_reuse_address:
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        self.socket.bind(self.server_addr)

    def server_activate(self):
        """开启监听"""
        
        self.socket.listen(self.backlog)

    def handle_request(self):
        """处理链接"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值