一、socket阻塞与非阻塞
- 阻塞式socket
阻塞式socket在默认情况下处于阻塞状态,即程序会一直等待,直到数据准备好或者等待超时才返回结果。这种方式容易造成资源浪费,同时影响程序的性能。下面是一个阻塞式socket的示例:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("www.baidu.com", 80))
data = s.recv(1024)
print(data)
s.close()
上面代码会一直等待,直到服务器响应数据,并将响应的数据打印出来。
- 非阻塞式socket
非阻塞式socket在默认情况下处于非阻塞状态,即程序不会一直等待,而是立即返回结果。如果没有数据准备好,则会返回异常,需要通过轮询等方式来等待数据的准备。下面是一个非阻塞式socket的示例:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setblocking(False)
try:
s.connect(("www.baidu.com", 80))
except Exception as e:
print(e)
data = None
while not data:
try:
data = s.recv(1024)
except Exception as e:
pass
print(data)
s.close()
上面代码将socket设置为非阻塞模式,所以connect调用可能会引发异常。当数据准备好后,通过while循环一直尝试读取数据,直到成功读取,然后将读取到的数据打印出来。
二、同步与异步
- 同步方式
在同步方式中,程序会一直等待,直到操作完成。这时程序不能继续执行其他任务,即是阻塞的。同步方式适用于处理简单的任务,但对于复杂的任务或者数据量较大的任务,会造成程序的阻塞,影响程序的性能。下面是一个同步方式的示例:
import requests
response = requests.get("http://www.baidu.com")
print(response.text)
上面代码会一直等待服务器响应,响应完后将响应内容打印出来。
- 异步方式
在异步方式中,程序可以同时处理多个任务或者数据,不需要一直等待,处理完成后回调通知程序结果。异步方式适用于复杂的任务或处理大量数据时,可以提高程序的性能。下面是一个异步方式的示例:
import asyncio
import aiohttp
async def main():
async with aiohttp.ClientSession() as session:
async with session.get("http://www.baidu.com") as response:
print(await response.text())
asyncio.run(main())
上面代码使用asyncio和aiohttp库实现异步方式的请求,可以同时处理多个请求,提高了程序的性能。
三、I/O模型
- 阻塞I/O模型
在阻塞I/O模型中,程序会一直等待,直到数据准备好或等待超时才继续执行。这种方式在处理数据时容易造成资源的浪费和程序性能的下降。下面是一个阻塞I/O模型的示例:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("www.baidu.com", 80))
s.send(b"GET / HTTP/1.1\r\nHost: www.baidu.com\r\nConnection: close\r\n\r\n")
data = s.recv(1024)
print(data)
s.close()
上面代码会一直等待服务器响应数据,如果响应数据较慢或者网络出现问题,程序就会一直处于等待状态。
- 非阻塞I/O模型
在非阻塞I/O模型中,程序会立即返回,处理完本次任务后可以继续执行其他任务。如果数据没有准备好,则会返回一个异常,需要通过轮询等方式等待数据准备就绪。下面是一个非阻塞I/O模型的示例:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setblocking(False)
try:
s.connect(("www.baidu.com", 80))
except Exception as e:
print(e)
s.send(b"GET / HTTP/1.1\r\nHost: www.baidu.com\r\nConnection: close\r\n\r\n")
data = None
while not data:
try:
data = s.recv(1024)
except Exception as e:
pass
print(data)
s.close()
上面代码将socket设置为非阻塞模式,并在数据发送后使用while循环轮询等待数据的准备。如果数据没有准备好,则会进行下一次轮询。
总的来说,socket阻塞与非阻塞、同步与异步、I/O模型是网络编程中比较重要的内容,掌握这些知识点对于编写高效的网络程序是十分有必要的。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解socket阻塞与非阻塞,同步与异步、I/O模型 - Python技术站