Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets 使用sendmsg、recvmsg的优点是什么_Sockets - Fatal编程技术网

Sockets 使用sendmsg、recvmsg的优点是什么

Sockets 使用sendmsg、recvmsg的优点是什么,sockets,Sockets,我正在学习Linux网络编程,并了解一些有关从套接字读取和写入数据的函数。recv,send,recvmsg,sendmesg。据我所知,recvmsg可以用来传递文件描述符,为套接字的读写增加超时。您能告诉我使用recvmsg、sendmsg比recv、send有什么优势吗? 非常感谢。recvmsg和sendmsg可以做以下几件事: 您可以执行分散/聚集缓冲区。例如,let's day您希望接收正好1MB的数据,但每个100KB只有10个缓冲区,然后您可以在单个recvmsg调用中填充每个缓

我正在学习Linux网络编程,并了解一些有关从套接字读取和写入数据的函数。recv,send,recvmsg,sendmesg。据我所知,recvmsg可以用来传递文件描述符,为套接字的读写增加超时。您能告诉我使用recvmsg、sendmsg比recv、send有什么优势吗?
非常感谢。

recvmsg和sendmsg可以做以下几件事:

  • 您可以执行分散/聚集缓冲区。例如,let's day您希望接收正好1MB的数据,但每个100KB只有10个缓冲区,然后您可以在单个recvmsg调用中填充每个缓冲区

  • 访问控制标志、辅助数据和IP数据包头字段。例如,对于UDP,您可以通过枚举从recvmsg返回的控制数据(启用某些IOCTL)来获取数据包所寻址的目标IP/端口地址


  • 旧问题,但recvmsg的另一个有用特性是用于在数据包中使用头/数据格式的协议。您可以设置一个用于接收标头的缓冲区,以及另一个用于接收数据的缓冲区

    到目前为止,后者只需要根据接收到的数据进行移位,就可以获得连续的数据,而无需任何(额外)内存拷贝。效率更高

    想象一下,您需要将一个非常大的文件分部分传输。对于经典recv调用,您需要创建如下缓冲区(伪代码):

    while(收到
    使用recvmsg,您可以跳过每个数据包的内存拷贝和许多系统调用:

    char * file = mmap(...); // Get a writable buffer for this file
    while(received < expectedFileSize)
    {
        char header[sizeof(Header)];
        struct iovec v[2] = { { header, sizeof(Header) }, { file + received, expectedFileSize - received } };
        msghdr msg = { NULL, 0, v, 2, 0, 0, 0 };
        int s = recvmsg(fd, &msg, 0); // Only one syscall here
        received += s - sizeof(Header);
    }
    
    char*file=mmap(…);//获取此文件的可写缓冲区
    while(接收<预期文件大小)
    {
    字符头[sizeof(头)];
    struct iovec v[2]={{header,sizeof(header)},{file+received,expectedFileSize-received};
    msghdr msg={NULL,0,v,2,0,0,0};
    int s=recvmsg(fd,&msg,0);//这里只有一个系统调用
    接收+=s-sizeof(报头);
    }
    
    不幸的是,这只能用于固定大小的标题

    反过来,假设您需要编写一个HTTP服务器

    此协议在发送内容之前发送一组标题。使用sendmsg几乎是执行此任务的1:1方式,其中一个线程正在编译头,而另一个线程正在编译内容

    在这种情况下,不需要添加锁定,因为每个线程都在其自己的缓冲区上执行,内容编译的处理不需要等待标题被完全编译(因为如果没有
    sendmsg
    ,您将需要标题大小来将内容附加到标题之后)

    char * file = mmap(...); // Get a writable buffer for this file
    while(received < expectedFileSize)
    {
        char header[sizeof(Header)];
        struct iovec v[2] = { { header, sizeof(Header) }, { file + received, expectedFileSize - received } };
        msghdr msg = { NULL, 0, v, 2, 0, 0, 0 };
        int s = recvmsg(fd, &msg, 0); // Only one syscall here
        received += s - sizeof(Header);
    }