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

yizhihongxing

接下来我会详细讲解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通过future处理并发问题

    Python通过引入future模块来处理并发问题,它提供了一个基本的抽象来处理诸如并发、异步等情况。下面是使用future模块处理并发的完整攻略: 引入future模块 在Python 2中,future模块是一个第三方库,在Python 3中已经被包含在标准库中,因此在Python 3中无需额外安装。 import concurrent.futures …

    python 2023年5月13日
    00
  • 使用Python读写多个sheet文件

    下面我将为你详细讲解如何使用Python读写多个sheet文件。本实例教程主要使用pandas库进行操作。 1. 导入pandas库 首先需要导入pandas库: import pandas as pd 2. 读取Excel文件 使用pd.read_excel()函数来读取Excel文件,可以通过设置sheet_name参数来指定需要读取的sheet,如果不…

    python 2023年5月13日
    00
  • Python requests模块安装及使用教程图解

    Python requests模块安装及使用教程图解 1. 安装requests模块 在终端中输入以下命令安装requests模块: pip install requests 注意: 如果你使用的是python3,需要修改命令为: pip3 install requests 安装完成后,我们就可以在脚本中使用requests模块了。 2. requests模…

    python 2023年5月14日
    00
  • Python机器学习之决策树算法实例详解

    下面是详细讲解“Python机器学习之决策树算法实例详解”的完整攻略,包括算法原理、Python实现和两个示例。 算法原理 决策树算法是一种基于树形结构的分类算法,其主要思想是通过对数据进行递归划分,构建一棵决策树,从而实现分类。决策树算法的实现过程如下: 选择一个特征作为根节点。 根据该特征将数据集划分为若干个子集。 对于每个子集,重复步骤1和步骤2,直到…

    python 2023年5月14日
    00
  • 分享Python 的24个编程超好用技巧

    分享Python的24个编程超好用技巧 Python是一种非常流行的编程语言,它具有简单易学、功能强大、可扩展性强等优点。本攻略将介绍Python的24个编程超好用技巧,帮助您更加高效地编写Python代码。 使用enumerate函数获取索引和值 使用enumerate函数可以同时获取列表或元组中的索引和值。以下是一个示例代码: fruits = [‘ap…

    python 2023年5月15日
    00
  • python如何修改文件时间属性

    要修改文件时间属性,需要使用Python内置的os模块。os模块提供了utime()函数用于修改文件的访问时间和修改时间。 下面是具体的步骤: 步骤一:导入os模块 import os 步骤二:获取文件路径和修改时间 首先,你需要准备好要修改的文件的路径和新的修改时间。我们可以使用os.path模块下的getatime()、getmtime()函数来获取文件…

    python 2023年6月3日
    00
  • mac 安装python网络请求包requests方法

    以下是关于在Mac上安装Python网络请求包requests方法的攻略: 在Mac上安装Python网络请求包requests方法 在Mac上安装Python网络请求包requests方法非常简单,可以使用pip命令进行安装。以下是在Mac上安装Python网络请求包requests方法的攻略。 安装pip 在Mac上安装Python网络请求包reques…

    python 2023年5月14日
    00
  • Python中的模块是什么?如何导入和使用模块?

    Python模块是什么? Python模块是一个包含了定义变量、函数、类等的可重用代码的文件,它允许我们在一个程序中分解代码成多个代码块。模块使得我们的代码更加的清晰、组织好,同时也方便其他开发者阅读和使用我们的代码。 Python中有两种类型的模块——内置模块和外部模块。内置模块是Python自带的,可以直接使用。外部模块则需要通过pip等包管理工具进行安…

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