Python socket recv阻塞

Python socket recv阻塞

Python socket recv阻塞

在使用Python进行socket编程时,我们经常会遇到一个问题:recv()函数阻塞。这是因为recv()函数会一直等待直到接收到数据,如果没有数据到来,程序就会一直停在那里,无法继续执行后续代码。这对于实际应用来说是非常不便的,因此我们需要了解如何处理这种 情况。

在本文中,我们将详细介绍Python中recv()函数的阻塞问题,并提供一些示例代码来展示如何解决这个问题。

示例代码1:基本的recv()阻塞

下面的代码是一个简单的socket服务器,它会一直等待客户端的连接,并接收客户端发送的数据。

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', 8080))
server.listen(5)

conn, addr = server.accept()
print(f'Connected by {addr}')

data = conn.recv(1024)  # 这里可能会阻塞
print(f'Received: {data.decode()}')

conn.close()
server.close()
Python

执行结果:

Connected by ('127.0.0.1', 12345)
Received: Hello from geek-docs.com

示例代码2:设置超时时间

为了避免recv()函数阻塞,我们可以设置一个超时时间。如果在超时时间内没有接收到数据,recv()函数会抛出一个socket.timeout异常。

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', 8080))
server.listen(5)

conn, addr = server.accept()
print(f'Connected by {addr}')

conn.settimeout(5)  # 设置超时时间为5秒

try:
    data = conn.recv(1024)
    print(f'Received: {data.decode()}')
except socket.timeout:
    print('No data received within 5 seconds')

conn.close()
server.close()
Python

执行结果:

Connected by ('127.0.0.1', 12345)
No data received within 5 seconds

示例代码3:使用非阻塞模式

另一种避免recv()阻塞的方法是将socket设置为非阻塞模式。在这种模式下,如果没有数据可接收,recv()函数会立即返回一个BlockingIOError异常。

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', 8080))
server.listen(5)

conn, addr = server.accept()
print(f'Connected by {addr}')

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

try:
    data = conn.recv(1024)
    print(f'Received: {data.decode()}')
except BlockingIOError:
    print('No data available')

conn.close()
server.close()
Python

执行结果:

Connected by ('127.0.0.1', 12345)
No data available

示例代码4:使用select模块

我们还可以使用select模块来检查socket是否有数据可读,从而避免阻塞。

import socket
import select

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', 8080))
server.listen(5)

conn, addr = server.accept()
print(f'Connected by {addr}')

readable, writable, exceptional = select.select([conn], [], [], 5)  # 等待5秒

if readable:
    data = conn.recv(1024)
    print(f'Received: {data.decode()}')
else:
    print('No data received within 5 seconds')

conn.close()
server.close()
Python

执行结果:

Connected by ('127.0.0.1', 12345)
Received: Hello from geek-docs.com

示例代码5:使用多线程

最后一种方法是使用多线程来处理每个客户端连接。这样,即使某个线程因为recv()阻塞而暂停,其他线程仍然可以正常工作。

import socket
import threading

def handle_client(conn, addr):
    print(f'Connected by {addr}')
    data = conn.recv(1024)
    print(f'Received: {data.decode()}')
    conn.close()

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', 8080))
server.listen(5)

while True:
    conn, addr = server.accept()
    client_thread = threading.Thread(target=handle_client, args=(conn, addr))
    client_thread.start()
Python

执行结果:

Connected by ('127.0.0.1', 12345)
Received: Hello from geek-docs.com

以上就是关于Python socket recv阻塞问题的几种解决方案。希望这篇文章能够帮助大家更好地理解和使用socket编程。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

登录

注册