• linux网络编程九:splice函数,高效的零拷贝


    from:http://blog.csdn.net/jasonliuvip/article/details/22600569

             linux网络编程九:splice函数,高效的零拷贝                     

    最近在看《Linux高性能服务器编程》,在此做个日记,以激励自己,同时分享于有需要的朋友。


    1. splice函数

    [cpp] view plain copy
     
    在CODE上查看代码片派生到我的代码片
    1. #include <fcntl.h>  
    2. ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags);  


    splice用于在两个文件描述符之间移动数据, 也是零拷贝。

    fd_in参数是待输入描述符。如果它是一个管道文件描述符,则off_in必须设置为NULL;否则off_in表示从输入数据流的何处开始读取,此时若为NULL,则从输入数据流的当前偏移位置读入。

    fd_out/off_out与上述相同,不过是用于输出。

    len参数指定移动数据的长度。

    flags参数则控制数据如何移动:

    • SPLICE_F_NONBLOCK:splice 操作不会被阻塞。然而,如果文件描述符没有被设置为不可被阻塞方式的 I/O ,那么调用 splice 有可能仍然被阻塞。
    • SPLICE_F_MORE:告知操作系统内核下一个 splice 系统调用将会有更多的数据传来。
    • SPLICE_F_MOVE:如果输出是文件,这个值则会使得操作系统内核尝试从输入管道缓冲区直接将数据读入到输出地址空间,这个数据传输过程没有任何数据拷贝操作发生。

    2. 使用splice时, fd_in和fd_out中必须至少有一个是管道文件描述符。

    调用成功时返回移动的字节数量;它可能返回0,表示没有数据需要移动,这通常发生在从管道中读数据时而该管道没有被写入的时候。

    失败时返回-1,并设置errno


    3. 代码:通过splice将客户端的内容读入到管道中, 再从管道中读出到客户端,从而实现高效简单的回显服务。整个过程未执行recv/send,因此也未涉及用户空间到内核空间的数据拷贝。

    [cpp] view plain copy
     
    在CODE上查看代码片派生到我的代码片
      1. //使用splice实现的回显服务器  
      2. #include <stdio.h>  
      3. #include <stdlib.h>  
      4. #include <unistd.h>  
      5. #include <sys/socket.h>  
      6. #include <netinet/in.h>  
      7. #include <arpa/inet.h>  
      8. #include <assert.h>  
      9. #include <errno.h>  
      10. #include <string.h>  
      11. #include <fcntl.h>  
      12.   
      13.   
      14. int main(int argc, char **argv)  
      15. {  
      16.   
      17.     if (argc <= 2) {  
      18.         printf("usage: %s ip port ", basename(argv[0]));  
      19.         return 1;  
      20.     }  
      21.       
      22.     const char *ip = argv[1];  
      23.     int port = atoi(argv[2]);  
      24.   
      25.     struct sockaddr_in address;  
      26.     bzero(&address, sizeof(address));  
      27.     address.sin_family = AF_INET;  
      28.     address.sin_port = htons(port);  
      29.     inet_pton(AF_INET, ip, &address.sin_addr);  
      30.   
      31.     int sock = socket(PF_INET, SOCK_STREAM, 0);  
      32.     assert(sock >= 0);  
      33.       
      34.     int reuse = 1;  
      35.     setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));  
      36.   
      37.     int ret = bind(sock, (struct sockaddr*)&address, sizeof(address));  
      38.     assert(ret != -1);  
      39.   
      40.     ret = listen(sock, 5);  
      41.     assert(ret != -1);  
      42.       
      43.     struct sockaddr_in client;  
      44.     socklen_t client_addrlength = sizeof(client);  
      45.       
      46.     int connfd = accept(sock, (struct sockaddr*)&client, &client_addrlength);  
      47.     if (connfd < 0) {  
      48.         printf("errno is: %s ", strerror(errno));  
      49.     }  
      50.     else {  
      51.         int pipefd[2];  
      52.                   
      53.         ret = pipe(pipefd);  //创建管道  
      54.         assert(ret != -1);  
      55.           
      56.                 //将connfd上的客户端数据定向到管道中  
      57.         ret = splice(connfd, NULL, pipefd[1], NULL,  
      58.                         32768, SPLICE_F_MORE | SPLICE_F_MOVE);  
      59.         assert(ret != -1);  
      60.           
      61.                 //将管道的输出定向到connfd上  
      62.         ret = splice(pipefd[0], NULL, connfd, NULL,  
      63.                         32768, SPLICE_F_MORE | SPLICE_F_MOVE);  
      64.         assert(ret != -1);                
      65.           
      66.         close(connfd);  
      67.     }  
      68.   
      69.       
      70.     close(sock);  
      71.   
      72.   
      73.   
      74.   
      75.     return 0;  
      76. }  
  • 相关阅读:
    运用Unity实现依赖注入[结合简单三层实例]
    利用WCF与Android实现图片上传并传参
    如何修改被编译后DLL文件
    ASP.NET基础之HttpHandler学习
    ASP.NET基础之HttpContext学习
    ASP.NET基础之HttpModule学习
    WCF学习笔记之事务编程
    WCF学习笔记之传输安全
    WCF心跳判断服务端及客户端是否掉线并实现重连接
    CLR_Via_C#学习笔记之事件
  • 原文地址:https://www.cnblogs.com/zhangzl/p/6053603.html
Copyright © 2020-2023  润新知