深入探讨Socket中的I_O多路复用
发布时间: 2024-02-25 04:41:05 阅读量: 18 订阅数: 17 ![](https://csdnimg.cn/release/wenkucmsfe/public/img/col_vip.0fdee7e1.png)
![](https://csdnimg.cn/release/wenkucmsfe/public/img/col_vip.0fdee7e1.png)
# 1. Socket简介和基础知识
### 1.1 Socket基础概念
在计算机网络中,Socket是通信的基本概念之一,它允许不同的计算机之间通过网络进行通信。Socket通常被描述为"套接字",是一种支持网络通信的数据结构。
在Socket编程中,通过Socket API建立连接、传输数据等操作。在TCP/IP协议中,通信的两端分别使用Socket来表示,服务器端通过ServerSocket监听客户端的连接请求,客户端通过Socket请求与服务器端建立连接,双方通过Socket进行数据传输。
### 1.2 Socket通信方式及原理
Socket通信方式包括面向连接的TCP和面向无连接的UDP两种。TCP提供可靠的、面向连接的数据流传输,通过三次握手建立连接,保证数据的可靠性;UDP则是一种无连接的传输协议,速度快,但不保证数据的可靠性。
Socket通信的原理是通过网络上的两个端点之间的数据传输进行通信。每个Socket都与一个IP地址和一个端口相关联,数据通过Socket传输时,被封装为数据包并通过网络传输到目标Socket。
### 1.3 Socket在网络编程中的应用
在网络编程中,Socket被广泛应用于各种场景,如HTTP、FTP、SMTP等协议都是基于Socket实现的。通过Socket编程,可以实现客户端与服务器的通信、文件传输、远程控制等功能。
Socket编程的核心是实现双方之间的数据传输和通信,开发人员可以利用Socket API来编写各种网络应用程序,实现实时数据传输、远程控制、分布式计算等功能。(Socket编程相关API在不同语言中略有差异,但基本原理相同)。
# 2. I/O多路复用基础
I/O多路复用是指操作系统内核一旦发现进程指定的一个或者多个I/O条件准备读取,它将通知该进程。这种机制的基本原理是使用一个线程轮询多个socket的状态,其不断的询问每个socket,看它是否有数据到达。I/O多路复用可以让单个线程高效地处理多个socket连接,提高了系统吞吐量。
在本章节中,将深入探讨I/O多路复用的基础知识,包括其概念、优势和适用场景,以及常见的I/O多路复用技术。让我们一起来深入了解!
### 2.1 理解I/O多路复用的概念
I/O多路复用是通过一种机制可以监控多个文件描述符,一旦某个文件描述符就绪(比如可读、可写等),就通过某种方式通知应用程序进行相应的读写等操作。常见的I/O多路复用技术包括select、poll、epoll等。
### 2.2 I/O多路复用的优势和适用场景
- 优势:
- 减少资源占用:通过一个线程管理多个socket,减少了线程间切换所带来的开销。
- 提高性能:能有效处理大量的并发连接,提高系统的吞吐能力。
- 简化编程:相比多线程/多进程,使用I/O多路复用能简化程序逻辑,提高代码的可维护性。
- 适用场景:
- 服务器需要同时与多个客户端保持长连接时。
- 需要处理大量的连接请求,但每个连接并发要求不高的情况下。
### 2.3 常见的I/O多路复用技术
#### **select**
select是最古老的一种I/O多路复用方式,适用于较小规模的连接数。它通过将文件描述符按位映射到位图中,监控所有文件描述符的状态变化。
```python
import select
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 12345))
server_socket.listen(5)
inputs = [server_socket]
outputs = []
exceptions = []
while True:
readable, writable, exceptional = select.select(inputs, outputs, exceptions)
for s in readable:
if s is server_socket:
client_socket, addr = server_socket.accept()
inputs.append(client_socket)
else:
data = s.recv(1024)
if data:
print(f"Received data: {data.decode()}")
else:
inputs.remove(s)
s.close()
```
#### **poll**
poll是对select的改进,没有最大文件描述符数量的限制。它采用链表结构存储文件描述符和事件信息。
```python
import select
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 12345))
server_socket.listen(5)
p = select.poll()
p.register(server_socket.fileno(), select.POLLIN)
fd_to_socket = {server_socket.fileno(): server_socket}
while True:
events = p.poll()
for fd, event in events:
if fd == server_socket.fileno():
client_socket, addr = server_socket.accept()
p.register(client_socket.fileno(), select.POLLIN)
fd_to_socket[client_socket.fileno()] = client_socket
else:
data = fd_to_socket[fd].recv(1024)
if data:
print(f"Received data: {data.decode()}")
else:
p.unregister(fd)
fd_to_socket[fd].close()
del fd_to_socket[fd]
```
#### **epoll**
epoll是Linux特有的一种I/O多路复用机制,无需遍历文件描述符列表,只需要调用epoll_wait等待就绪事件。
```python
import select
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 12345))
server_socket.listen(5)
epoll = select.epoll()
epoll.register(server_socket.fileno(), select.EPOLLIN)
fd_to_socket = {server_socket.fileno(): server_socket}
while True:
events = epoll.poll()
for fd, event in events:
if fd == server_socket.fileno():
client_sock
```
0
0
相关推荐
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)