Python实现socket非阻塞通讯功能示例

接下来我会详细讲解Python实现socket非阻塞通讯的完整攻略。

什么是Socket非阻塞通讯

在网络编程中,我们常常需要使用Socket来进行网络通信。而在Socket的使用过程中,一般都会采用阻塞式编程方式。即当Socket收到请求或发送数据时,程序会一直等待,直到数据传输完成才会执行下一步操作。

而Socket非阻塞通讯则是指在Socket通信过程中,程序不会一直等待。当Socket收到请求或发送数据时,程序可以直接进行下一步操作,不必等待Socket传输完成。这种方式可以大大提高程序的并发性。

如何实现Socket非阻塞通讯

实现Socket非阻塞通讯的方式有多种。其中一种较为常见的方式是使用Python的select模块和非阻塞式Socket。

1. 创建非阻塞式Socket

我们可以使用Python的socket模块来创建Socket,并将其设置为非阻塞式:

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(False)
sock.bind(('127.0.0.1', 3000))
sock.listen(5)

在上面的代码中,我们使用了socket模块创建了一个TCP类型的Socket,并将其设置为非阻塞式。由于设置了非阻塞式,Socket在进行数据传输时就不会一直等待,而是会立即返回数据状态。同时,我们将Socket绑定到本地端口3000上,并开始监听客户端的连接请求。

2. 使用select模块进行数据交互

在Socket通信过程中,我们需要不断检查Socket是否有数据到来或者数据是否已经发送完成。这时我们可以使用Python的select模块。相较于阻塞式编程,这种方式会减少无效的等待时间,提升程序性能。

首先,我们需要使用select模块来创建I/O对象和I/O读写列表:

import select

inputs = [sock]
outputs = []

在上面的代码中,我们定义了一个reads列表和一个writes列表。分别用来存储需要读取和需要写入数据的Socket对象。

然后,我们可以使用select模块的select函数来进行I/O对象列表的监听:

while inputs:
    rs, ws, xs = select.select(inputs, outputs, inputs)

    for r in rs:
        # 处理读取事件
        pass

    for w in ws:
        # 处理写入事件
        pass

    for x in xs:
        # 处理异常事件
        pass

在上面的代码中,调用select.select()函数来监听输入对象列表,监听输出对象列表和监听异常条件,其中:

  • rs: 表示可读I/O列表
  • ws: 表示可写I/O列表
  • xs: 表示异常I/O列表

在监听事件之后,我们需要根据当前的事件类型来进行读写操作。举个例子,如果rs列表中有可读数据,那么我们可以使用recv函数来读取数据:

for r in rs:
    data = r.recv(1024)
    if data:
        # 处理数据
    else:
        # Socket连接已关闭
        inputs.remove(r)
        r.close()

在上面的代码中,我们使用recv()函数来读取数据,处理完数据后如果需要断开连接则调用close()函数关闭Socket。如果当前读取的Socket已经关闭,则从输入对象列表中删除它。

示例

接下来,我们可以看一下使用Python实现Socket非阻塞通讯的一个例子:

import select
import socket

# 创建非阻塞式Socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(False)
sock.bind(('127.0.0.1', 3000))
sock.listen(5)

# 初始化select模块输入输出列表
inputs = [sock]
outputs = []

while inputs:
    rs, ws, xs = select.select(inputs, outputs, [])

    for r in rs:
        if r is sock:
            # 处理连接请求
            conn, addr = sock.accept()
            conn.setblocking(False)
            inputs.append(conn)
        else:
            data = r.recv(1024)
            if data:
                # 处理数据
                pass
            else:
                inputs.remove(r)
                r.close()

    for w in ws:
        # 处理写入事件
        pass

在上面的示例中,我们首先创建了一个非阻塞式Socket并将其绑定到端口3000上。然后我们创建了一个select模块的输入输出列表。

在程序运行时,我们首先使用select模块对输入输出列表进行监听。当rs列表中有可以读取的数据时,我们使用recv()函数读取数据并进行处理。当ws列表中有可以写入的数据时,我们使用send()函数写入数据。同时,当rs列表中有新的连接请求时,我们使用accept()函数接收连接,并将其添加到inputs列表中。

这个例子实现了一个简单的非阻塞式Socket服务器,并且可以同时接收多个客户端的连接和数据请求。

示例2

下面是另一个示例,可以让代码更加清晰明了:

import socket
import select

HOST = '' 
PORT = 13333
MAX_LISTEN = 100
RECV_BUF_SIZE = 4096
EOL1 = b'\n\n'
EOL2 = b'\n\r\n'

def handle_client(connection):
    data = connection.recv(RECV_BUF_SIZE)
    print(data.decode('utf-8'))
    connection.send(bytes('HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nHello', 'utf-8'))
    connection.close()


def handle_server(server_socket):
    server_socket.setblocking(0)
    server_socket.listen(MAX_LISTEN)
    inputs = [server_socket]
    outputs = []
    while True:
        readable, writeable, exceptional = select.select(inputs, outputs, inputs)
        for r in readable:
            if r in inputs:
                if r is server_socket:
                    connection, client_address = r.accept()
                    connection.setblocking(0)
                    inputs.append(connection)
                else:
                    handle_client(r)
                    inputs.remove(r)
                    if r in outputs:
                        outputs.remove(r)
        for w in writeable:
            pass
        for e in exceptional:
            pass


if __name__ == '__main__':
    try:
        server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        server_socket.bind((HOST, PORT))
        print('HTTP Server listening on', PORT)
        handle_server(server_socket)
    except Exception as e:
        print(e)

在这个例子中,我们首先定义了一个handle_client()函数来处理客户端请求。并定义了一个handle_server()函数来启动Non-Blocking Socket服务器。

然后,在handle_server函数中,我们设置了socket为非阻塞式,使用select模块来进行对象列表的监听。在监听到有readable对象时,我们进行数据读取和处理;当对象可以writeable时,我们进行数据写入处理。

在这个例子中,我们实现了一个简单的HTTP服务器,并且使其支持非阻塞式Socket通信。

【注】以上代码均未经过安全性和效率方面的审查和测试,仅作为示例。实际使用中需谨慎。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python实现socket非阻塞通讯功能示例 - Python技术站

(1)
上一篇 2023年6月6日
下一篇 2023年6月6日

相关文章

  • Python Parser的用法

    PythonParser的用法 PythonParser是Python中用于解析和处理网页的一个库。它提供了许多API,可以帮助开发者高效地获取并处理网页上的数据。下面我们将详细介绍PythonParser的用法。 安装和引入 PythonParser可以使用pip工具进行安装,安装方式如下: pip install pythonparser 安装完成之后,…

    python 2023年5月13日
    00
  • Python安装tar.gz格式文件方法详解

    Python安装tar.gz格式文件方法详解 在Linux环境下,常见的一种文件格式就是tar.gz格式。Python项目也常常发布这种格式的文件。本文将详细介绍如何在Linux环境下安装tar.gz格式的Python文件。 步骤一 下载文件 首先找到需要安装的Python文件的下载链接,通过wget或者curl命令下载,如下面的示例: $ wget htt…

    python 2023年6月5日
    00
  • python中统计相同字符的个数方法实例

    标题:Python中统计相同字符的个数方法实例 在Python中,要统计一个字符串中相同字符的个数,可以采用以下方法: 使用Python标准库中的collections模块中的Counter类 from collections import Counter s = "abbcccdddd" count = Counter(s) print…

    python 2023年6月5日
    00
  • Python利用逻辑回归模型解决MNIST手写数字识别问题详解

    Python利用逻辑回归模型解决MNIST手写数字识别问题详解 介绍 在本文中,我们将使用逻辑回归模型解决手写数字识别问题。我们将使用MNIST数据集,该数据集是图像识别领域的标准数据集之一。我们将使用Python和Scikit-Learn库。 步骤 步骤如下: 加载数据。 数据预处理。 训练逻辑回归模型。 评估模型。 使用模型进行预测。 步骤一:加载数据 …

    python 2023年6月6日
    00
  • python远程调用rpc模块xmlrpclib的方法

    使用Python远程调用RPC模块xmlrpclib的方法,可以通过以下步骤完成。 步骤一:开启服务端 在服务器上创建一个Python脚本,作为服务端的脚本,使用SimpleXMLRPCServer模块开启服务监听,如下所示: from SimpleXMLRPCServer import SimpleXMLRPCServer import os def ge…

    python 2023年6月3日
    00
  • Python实现 版本号对比功能的实例代码

    以下是Python实现版本号对比功能的完整攻略: 步骤1:导入必要的库 在Python中实现版本号对比功能需要导入re库。以下是一个示例代码: import re 步骤2:定义版本号比较函数 定义版本号比较函数是实现版本号对比功能的关键步骤。以下是一个示例代码: def compare_version(version1, version2): v1 = [i…

    python 2023年5月14日
    00
  • python如何从文件读取数据及解析

    Python是一种非常适合数据处理和分析的语言,而从文件中读取数据和解析数据是处理数据的一个重要环节。下面将详细讲解Python如何从文件读取数据及解析的完整攻略。 读取文件 Python中可以使用open()函数打开文件,并使用不同的模式(mode)对文件进行读写操作。常见的模式有: ‘r’:只读模式,如果文件不存在则直接报错; ‘w’:只写模式,如果文件…

    python 2023年6月5日
    00
  • E: 无法定位软件包 python3-pip问题及解决

    Python3-pip是Python3的一个流行工具,用于管理和安装Python3软件包。但有时会遇到” E: 无法定位软件包 python3-pip”的问题。此问题通常是由于软件仓库缺少软件包,或者更新源列表信息不正确导致的。以下是解决此问题的详细步骤: 1. 更新软件源列表 首先,运行以下命令更新软件源列表: sudo apt-get update 这将…

    python 2023年5月14日
    00
合作推广
合作推广
分享本页
返回顶部