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中字符串的操作方法大全

    Python中字符串的操作方法大全 在Python中,字符串是一种不可变的序列类型,可以使用多种方法进行操作。本文将介绍Python中字符串的操作方法,包括字符串的创建、字符串的索引和切片、字符串的拼接和重复、字符串的查和替换、字符串的大小写转换、字符串的分割和连接、字符串格式化等。 字符串的创建 在Python中,可以使用单引号、引号或三引号来创建字符串。…

    python 2023年5月13日
    00
  • python语音信号处理详细教程

    Python 语音信号处理详细教程攻略 简介 本教程旨在帮助初学者了解 Python 中的语音信号处理,包括频率、FFT、STFT、滤波、mfcc 等基础操作。本教程适合对语音信号处理感兴趣的人士,对 Python 语言有一定基础,希望能够快速入门语音信号处理的内容。 准备工作 在开始学习本教程之前,请确保已经完成以下准备工作:- 安装 Python 环境(…

    python 2023年6月6日
    00
  • pygame实现井字棋之第三步逻辑优化

    让我来详细讲解“pygame实现井字棋之第三步逻辑优化”的完整攻略。 1. 实现功能 在实现“pygame实现井字棋之第三步逻辑优化”之前,我们首先要了解这个游戏需要实现哪些功能。在之前的第二步代码(https://www.jianshu.com/p/e0f0c430f5fe)中,我们已经实现了一个可以在窗口中显示的井字棋游戏,用户可以通过鼠标点击的方式在窗…

    python 2023年5月14日
    00
  • Python实现完整的事务操作示例

    下面我将为您详细讲解Python实现完整的事务操作示例的完整攻略。 如何实现Python的事务操作? Python实现事务操作的步骤如下: 连接数据库:使用Python的数据库连接工具(例如Python的pymysql模块)连接目标数据库; 开启事务:通过执行SQL语句“BEGIN”来开启一个事务; 执行SQL语句:在事务中执行需要执行的SQL语句; 提交事…

    python 2023年5月19日
    00
  • Python爬虫实例扒取2345天气预报

    下面是Python爬虫实例扒取2345天气预报的完整攻略: 1. 准备工作 在开始实现爬虫之前,需要安装Python环境和必要的爬虫库。接下来是具体的准备工作: 1.1 安装Python环境 Python的安装非常简单,可以到Python官网上下载安装包,根据图形化安装界面进行安装。 1.2 安装必要的Python库 本次爬虫我们需要使用以下几个Python…

    python 2023年5月19日
    00
  • Python Request类源码实现方法及原理解析

    Python Request类源码实现方法及原理解析 概述 本文将介绍 Python 中常用的 HTTP 请求库 —— requests 的核心模块 Request 的源码实现方法及原理解析。首先,我们将介绍 Request 类的基本使用方法和常用属性和方法。然后,我们将解析 Request 类在底层的实现原理,并通过源码分析来深入了解它是如何实现 HTTP…

    python 2023年5月19日
    00
  • 一文助你搞懂参数传递原理解析(java、go、python、c++)

    一文助你搞懂参数传递原理解析 在编程中,参数传递是一个非常重要的概念。不同的编程语言有不同的参数传递方式,本文将介绍Java、Go、Python和C++中的参数传递原理,并提供两个示例。 Java中的参数传递 在Java中,参数传递是按值传递的。这意味着,当我们将一个变量作为参数传递给一个方法时,实际上传递的是该变量的值,而不是变量本身。以下是一个示例代码:…

    python 2023年5月15日
    00
  • 用Python写一个自动木马程序

    首先,我们需要明确一下,在未经授权情况下编写、传播木马程序是犯罪行为,严重的甚至会涉及到法律责任。因此,我们的讨论只是在技术层面上,不鼓励任何人使用这项技术进行非法活动。 一、编写自动木马程序攻略 编写一个自动木马程序,可以分为以下几个步骤: 1.选择适合的编程语言:Python等脚本语言比较适合编写简单的木马程序,因为其语言特性、模块库、开发效率都比较高。…

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