在 socket 通信中,分散读和集中写是两种常见的 I/O 模型。
分散读(scatter read):在分散读模型中,应用程序可以在一次 readv() 系统调用中从 socket 读取多个缓冲区的数据。这意味着可以一次性读取多个数据包,而不必为每个数据包执行单独的 read() 调用。这种方式可以减少系统调用的次数,提高读取效率。
集中写(gather write):在集中写模型中,应用程序可以在一次 writev() 系统调用中将多个缓冲区的数据写入 socket。这意味着可以一次性发送多个数据包,而不必为每个数据包执行单独的 write() 调用。这种方式可以减少系统调用的次数,提高发送效率。
分散读和集中写可以通过使用 readv() 和 writev() 系统调用来实现。这两个系统调用允许应用程序指定一个向量(vector),其中包含多个缓冲区的指针和缓冲区的长度。这样可以一次性读取或写入多个缓冲区的数据。
以下是一个简单的示例代码,展示了如何在 socket 通信中使用分散读和集中写:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
void sendData(int socket, const char *data, size_t dataSize)
{
struct iovec iov[2];
char buffer[1024];
// 将数据分散到两个缓冲区
iov[0].iov_base = data;
iov[0].iov_len = dataSize / 2;
iov[1].iov_base = buffer;
iov[1].iov_len = dataSize - iov[0].iov_len;
// 使用 writev 进行集中写
ssize_t bytesWritten = writev(socket, iov, 2);
if (bytesWritten == -1)
{
perror("Failed to send data");
exit(EXIT_FAILURE);
}
printf("Sent %zu bytes of data\n", bytesWritten);
}
void receiveData(int socket)
{
struct iovec iov[2];
char buffer1[1024], buffer2[1024];
// 创建两个缓冲区来接收数据
iov[0].iov_base = buffer1;
iov[0].iov_len = sizeof(buffer1);
iov[1].iov_base = buffer2;
iov[1].iov_len = sizeof(buffer2);
// 使用 readv 进行分散读
ssize_t bytesRead = readv(socket, iov, 2);
if (bytesRead == -1)
{
perror("Failed to receive data");
exit(EXIT_FAILURE);
}
printf("Received %zu bytes of data\n", bytesRead);
// 输出接收到的数据
printf("Received data: %s\n", buffer1);
printf("Received data: %s\n", buffer2);
}
int main()
{
int serverSocket, clientSocket;
struct sockaddr_in serverAddress, clientAddress;
socklen_t addressLength = sizeof(clientAddress);
// 创建一个 TCP socket
if ((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Failed to create socket");
exit(EXIT_FAILURE);
}
// 绑定 socket 到本地回环地址和端口 12345
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = INADDR_LOOPBACK;
serverAddress.sin_port = htons(12345);
if (bind(serverSocket, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) == -1)
{
perror("Failed to bind socket");
exit(EXIT_FAILURE);
}
// 开始监听连接
if (listen(serverSocket, 1) == -1)
{
perror("Failed to listen on socket");
exit(EXIT_FAILURE);
}
printf("Waiting for client connection...\n");
// 接受客户端连接
if ((clientSocket = accept(serverSocket, (struct sockaddr *)&clientAddress, &addressLength)) == -1)
{
perror("Failed to accept connection");
exit(EXIT_FAILURE);
}
printf("Connected with client\n");
// 发送数据给客户端
const char *data = "Hello, client!";
sendData(clientSocket, data, strlen(data));
// 接收客户端的数据
receiveData(clientSocket);
// 关闭连接
close(clientSocket);
close(serverSocket);
return 0;
}
在这个示例中,创建了一个 TCP 服务器和一个 TCP 客户端。通过在客户端和服务器之间建立连接,可以使用分散读和集中写来高效地传输数据。
请注意,这只是一个简单的示例,实际应用中可能需要更多的错误处理和数据处理逻辑。分散读和集中写可以在许多情况下提高 socket 通信的性能,但具体的性能提升效果可能会受到网络延迟、带宽等因素的影响。
标签:socket,iov,通信,分散,缓冲区,include,data From: https://www.cnblogs.com/yubo-guan/p/18010850