首页 > 其他分享 >socket通信中的分散读和集中写

socket通信中的分散读和集中写

时间:2024-02-07 13:34:06浏览次数:24  
标签:socket iov 通信 分散 缓冲区 include data

在 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

相关文章

  • Linux下socket通信中的带外数据
    目录简介示例简介在Linux下的socket通信中,带外数据(Out-of-Band,简称OOB)是一种特殊的数据传输方式。通常,socket通信中的数据是按照顺序发送和接收的,即所谓的带内数据(In-Band)。然而,在某些情况下,可能需要发送一些紧急或重要的数据,这些数据不适合通过常规的带内数据传输方式发送,因为......
  • 【面试突击】网络通信面试实战
    网络通信面试实战Socket工作原理Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口,其实就是一个门面模式,将底层复杂的通信操作给封装起来对外提供接口。简单来说就是Socket把TPC/IP协议给封装了起来,我们的程序进行网络通信都是通过Socket来完成的!也就是说当......
  • socket地址API
    目录主机字节序和网络字节序通用socket地址专用socket地址ip地址转换函数主机字节序和网络字节序在Linux系统中,主机字节序(HostByteOrder)和网络字节序(NetworkByteOrder)是两个重要的概念。主机字节序是指CPU直接处理数据时使用的字节序。在x86架构的Linux系统中,主......
  • esp32笔记[14]-使用软串口双机通信
    摘要两个esp32之间使用软串口(SoftSerial)进行通信.平台信息ArduinoIDE:2.2.1node_a:esp32c3node_b:esp32s2原理简介软串口SoftSerial[https://www.arduino.cc/reference/en/libraries/espsoftwareserial/][https://blog.csdn.net/qq_43126437/article/details/106166......
  • 全国产T3+FPGA的SPI与I2C通信方案分享
    近年来,随着中国新基建、中国制造2025规划的持续推进,单ARM处理器越来越难胜任工业现场的功能要求,特别是如今能源电力、工业控制、智慧医疗等行业,往往更需要ARM+FPGA架构的处理器平台来实现例如多路/高速AD采集、多路网口、多路串口、多路/高速并行DI/DO、高速数据并行处理等特定......
  • WebSocket 协议 message, ping , Pong, 消息
    以前一直不明白,WebSocket 已经有了message回调函数,可以接收任何的消息,按理说,ping和pong也只是  message 众多消息类型中的两个消息特里,直到看到 <<WebSocket协议 >>的定义,才明白,为什么了 一、数据帧(DataFraming)WebSocket协议中,数据是通过数据帧来传递的,协议......
  • 《UNIX网络编程 卷2:进程间通信(第2版)》PDF
    内容简介《UNIX网络编程.卷2:进程间通信(第2版)》是一部UNIX网络编程的经典之作!进程间通信(IPC)几乎是所有Unix程序性能的关键,理解IPC也是理解如何开发不同主机间网络应用程序的必要条件。《UNIX网络编程.卷2:进程间通信(第2版)》从对PosixIPC和SystemVIPC的内部结构开始讨论,全面......
  • USART串口通信
    一.通信接口半双工(HalfDuplex):数据传输指数据可以在一个信号载体的两个方向上传输,但是不能同时传输全双工(FullDuplex):是指在通信过程中,数据可以在两个方向上同时传输的一种模式。SCL,SCLK为时钟线,I2C,SPI为同步通信USARTCANUSB无时钟线,为异步通信,需要约定采样频率,并需要......
  • Linux进程间通信_共享内存和消息队列
    本文对SystemV标准的共享内存和消息队列这两种进程间通信方式进行讨论,涉及原理、系统调用接口以及相关的内核数据结构,并给出相关示例代码。SystemV共享内存基本原理进程间通信必须要让不同的进程看到同一份内存资源,因为进程具有独立性,所以这份内存资源是操作系统提供的,接口是由......
  • Caused by: java.lang.IllegalStateException: A unix domain socket connection requ
    Causedby:java.lang.IllegalStateException:Aunixdomainsocketconnectionrequiresepollorkqueueandneitherisavailable出现这个错误,首先确保自己的操作系统是否支持epoll,或者kqueue。如果支持。请导入netty的大库,lettuce中好像缺失了一部分,我怀疑是这是怀疑,......