在网络编程中,我们经常听到阻塞(Blocking)和非阻塞(Non-Blocking)、异步(Asynchronous)和非异步(Synchronous)这些概念。那么这些概念到底是什么意思呢?下面就让我来为大家简单介绍一下。
阻塞与非阻塞
阻塞网络指的是当一个进程向另一个进程发送请求时,如果对方没有响应,那么当前进程会一直等待,直到对方返回结果或者超时。这种方式可以保证数据的可靠性,但是会导致程序的响应速度变慢,因为程序可能会因为等待而被阻塞住。
相反,非阻塞网络是指当一个进程向另一个进程发送请求时,即使对方没有响应,当前进程也可以继续执行其他任务,不必等待对方的响应。这种方式可以提高程序的响应速度,但是会导致数据的可靠性降低,因为有可能因为没有等待到对方的响应而导致数据传输错误。下面是一个使用阻塞socket编写的TCP客户端代码示例:
python
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('localhost', 5000)
client_socket.connect(server_address)
#发送数据
message = 'Hello, World!'
client_socket.sendall(message.encode())
#接收数据
data = client_socket.recv(1024)
print('Received: {}'.format(data.decode()))
# 关闭连接
client_socket.close()
上述代码中,当客户端调用 connect()方法时,如果服务器没有响应,客户端将会被阻塞住,直到服务器返回结果或者超时。如果服务器没有正确响应,客户端将会一直等待,直到服务器返回结果或者超时。接下来,让我们来看一下使用非阻塞socket编写的TCP客户端代码示例:
python
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.setblocking(False)
server_address = ('localhost', 5000)
try:
client_socket.connect(server_address)
except BlockingIOError:
pass
# 发送数据
message = 'Hello, World!'
while True:
try:
client_socket.sendall(message.encode())
break
except OSError:
pass
# 接收数据
data = b''
while True:
try:
chunk = client_socket.recv(1024)
if not chunk:
break
data += chunk
except BlockingIOError:
pass
print('Received: {}'.format(data.decode()))
# 关闭连接
client_socket.close()
在上述代码中,当客户端调用 connect() 方法时,如果服务器没有响应,客户端不会被阻塞住,而是立即返回。如果服务器没有正确响应,客户端会定期检查是否已经连接成功,直到连接成功或者超时。
异步与非异步
异步网络指的是当一个进程向另一个进程发送请求时,当前进程可以继续执行其他任务,而不必等待对方的响应。但是当对方响应时,当前进程需要进行回调操作,处理对方返回的结果。这种方式可以提高程序的响应速度,同时也可以保证数据的可靠性。
相反,非异步网络是指当一个进程向另一个进程发送请求时,当前进程必须等待对方的响应,并且只有在接收到对方的响应后才能继续执行其他任务。这种方式虽然可以保证数据的可靠性,但是会导致程序的响应速度变慢。下面是一个使用异步socket编写的TCP客户端代码示例:
python
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#设置为非阻塞模式
client_socket.setblocking(False)
server_address = ('localhost', 5000)
#连接服务器
try:
client_socket.connect(server_address)
except BlockingIOError:
pass
#发送数据
message = 'Hello, World!'
data_to_send = message.encode()
sent = 0
while sent < len(data_to_send):
try:
# 发送数据
sent += client_socket.send(data_to_send[sent:])
except BlockingIOError:
pass
#接收数据
def handle_response(key, mask):
global client_socket
data = b''
while True:
try:
chunk = client_socket.recv(1024)
if not chunk:
break
data += chunk
except BlockingIOError:
break
print('Received: {}'.format(data.decode()))
client_socket.close()
#注册回调函数
import selectors
selector = selectors.DefaultSelector()
selector.register(client_socket, selectors.EVENT_READ, handle_response)
#开始事件循环
while True:
events = selector.select()
for key, mask in events:
callback = key.data
callback(key, mask)
在上述代码中,我们首先将客户端socket设置为非阻塞模式,然后使用 connect() 方法连接服务器。接下来,我们发送数据并通过注册回调函数的方式接收数据。当有数据到达时,回调函数将会被自动调用。
总结
阻塞和非阻塞主要区别在于是否等待对方响应,而异步和非异步主要区别在于回调操作的方式。在实际的网络编程中,我们需要根据具体的需求选择合适的方式来进行开发,以满足程序的特定需求。