Python Socket阻塞和非阻塞

Socket是一个在网络编程中常用的工具,它提供了一种实现网络通信的方法。在Python中,我们可以使用socket库来创建和管理Socket。在网络通信中,通常会遇到阻塞和非阻塞两种不同的模式。本文将介绍Python Socket的阻塞和非阻塞模式,并提供相应的代码示例。

1. Socket阻塞模式

在Socket阻塞模式下,当我们调用一个阻塞式的Socket方法时,程序会一直等待,直到操作完成或超时。在这种模式下,当我们进行网络通信时,程序会停止执行,直到接收或发送完成。

示例代码

import socket

# 创建Socket对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 12345))
server_socket.listen(1)

# 阻塞式等待客户端连接
print("等待客户端连接...")
client_socket, addr = server_socket.accept()
print("客户端已连接:", addr)

# 阻塞式接收数据
print("等待接收数据...")
data = client_socket.recv(1024)
print("接收到的数据:", data.decode())

# 阻塞式发送数据
print("发送数据中...")
client_socket.send("Hello, Client!".encode())

# 关闭Socket连接
client_socket.close()
server_socket.close()

在上面的代码中,我们创建了一个服务器Socket对象,并使用accept()方法阻塞等待客户端的连接。接下来,我们使用recv()方法阻塞式地接收客户端发送的数据,并使用send()方法阻塞式地发送响应数据。

在阻塞模式下,当Socket对象执行accept()recv()send()等方法时,程序会停止在这里等待,直到操作完成或超时。这种模式下的网络通信是一种同步的方式,只有完成当前操作后才能继续执行后续代码。

2. Socket非阻塞模式

相对于阻塞模式,Socket的非阻塞模式允许我们在进行网络通信时,程序可以同时执行其他任务,而不是一直等待操作完成。在非阻塞模式下,Socket对象的方法会立即返回,不管操作是否完成。

示例代码

import socket

# 创建Socket对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 12345))
server_socket.listen(1)

# 设置非阻塞模式
server_socket.setblocking(False)

# 非阻塞式等待客户端连接
while True:
    try:
        client_socket, addr = server_socket.accept()
        print("客户端已连接:", addr)
        break
    except BlockingIOError:
        pass

# 非阻塞式接收数据
data = b""
while True:
    try:
        chunk = client_socket.recv(1024)
        if chunk:
            data += chunk
        else:
            break
    except BlockingIOError:
        pass
print("接收到的数据:", data.decode())

# 非阻塞式发送数据
while True:
    try:
        client_socket.send("Hello, Client!".encode())
        break
    except BlockingIOError:
        pass

# 关闭Socket连接
client_socket.close()
server_socket.close()

在上面的代码中,我们首先创建了一个服务器Socket对象,并使用setblocking(False)方法将其设置为非阻塞模式。接下来,我们使用一个无限循环来不断尝试接收客户端的连接,直到成功连接为止。在接收数据和发送数据的过程中,我们同样使用无限循环来持续尝试操作,直到操作成功为止。

在非阻塞模式下,当Socket对象执行accept()recv()send()等方法时,程序会立即返回,不会等待操作完成。因此,我们需要使用循环来不断尝试操作,直到操作成功。

3. 阻塞与非阻塞模式的对比

下面是阻塞和非阻塞模式的对比表格:

阻塞模式 非阻塞模式
连接