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

1. splice函数

    #include <fcntl.h>
    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,因此也未涉及用户空间到内核空间的数据拷贝。

    //使用splice实现的回显服务器
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <assert.h>
    #include <errno.h>
    #include <string.h>
    #include <fcntl.h>
     
     
    int main(int argc, char **argv)
    {
     
        if (argc <= 2) {
            printf("usage: %s ip port\n", basename(argv[0]));
            return 1;
        }
        
        const char *ip = argv[1];
        int port = atoi(argv[2]);
     
        struct sockaddr_in address;
        bzero(&address, sizeof(address));
        address.sin_family = AF_INET;
        address.sin_port = htons(port);
        inet_pton(AF_INET, ip, &address.sin_addr);
     
        int sock = socket(PF_INET, SOCK_STREAM, 0);
        assert(sock >= 0);
        
        int reuse = 1;
        setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
     
        int ret = bind(sock, (struct sockaddr*)&address, sizeof(address));
        assert(ret != -1);
     
        ret = listen(sock, 5);
        assert(ret != -1);
        
        struct sockaddr_in client;
        socklen_t client_addrlength = sizeof(client);
        
        int connfd = accept(sock, (struct sockaddr*)&client, &client_addrlength);
        if (connfd < 0) {
            printf("errno is: %s\n", strerror(errno));
        }
        else {
            int pipefd[2];
                    
            ret = pipe(pipefd);  //创建管道
            assert(ret != -1);
            
                    //将connfd上的客户端数据定向到管道中
            ret = splice(connfd, NULL, pipefd[1], NULL,
                            32768, SPLICE_F_MORE | SPLICE_F_MOVE);
            assert(ret != -1);
            
                    //将管道的输出定向到connfd上
            ret = splice(pipefd[0], NULL, connfd, NULL,
                            32768, SPLICE_F_MORE | SPLICE_F_MOVE);
            assert(ret != -1);                
            
            close(connfd);
        }
     
        
        close(sock);
     
     
     
     
        return 0;
    }
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384934.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

sys/queue.h

概述 sys/queue.h是LINUX/UNIX系统下面的一个标准头文件&#xff0c;用一系列的数据结构定义了一队列。包括singly-lined list, list, simple queue(Singly-linked Tail queue), tail queue, circle queue五种。 引用此头文件对这五种数据结构的描述&#xff1a; A singly-lin…

sys/queue.h分析(图片复制不过来,查看原文)

这两天有兴趣学习使用了下系统头文件sys/queue.h中的链表/队列的实现&#xff0c;感觉实现的很是优美&#xff0c;关键是以后再也不需要自己实现这些基本的数据结构了&#xff0c;哈哈&#xff01; 我的系统环境是 正好需要使用队列&#xff0c;那么本篇就以其中的尾队列&…

线程池原理及C语言实现线程池

备注&#xff1a;该线程池源码参考自传直播客培训视频配套资料&#xff1b; 源码&#xff1a;https://pan.baidu.com/s/1zWuoE3q0KT5TUjmPKTb1lw 密码&#xff1a;pp42 引言&#xff1a;线程池是一种多线程处理形式&#xff0c;大多用于高并发服务器上&#xff0c;它能合理有效…

iptables 的mangle表

mangle表的主要功能是根据规则修改数据包的一些标志位&#xff0c;以便其他规则或程序可以利用这种标志对数据包进行过滤或策略路由。 内网的客户机通过Linux主机连入Internet&#xff0c;而Linux主机与Internet连接时有两条线路&#xff0c;它们的网关如图所示。现要求对内网进…

Linux常用命令(一)

history 查看历史命令 ctrlp 向上翻历史纪录 ctrln 向下翻历史纪录 ctrlb 光标向左移动 ctrlf 光标向右移动 ctrla 光标移动到行首 ctrle 光标移动到行尾 ctrlh 删除光标前一个 ctrld 删除光标后一个 ctrlu 删除光标前所有 ctrlL clear命令 清屏 tab键可以补全命令/填充路径…

ip route / ip rule /iptables 配置策略路由

Linux 使用 ip route , ip rule , iptables 配置策略路由 要求192.168.0.100以内的使用 10.0.0.1 网关上网&#xff0c;其他IP使用 20.0.0.1 上网。 首先要在网关服务器上添加一个默认路由&#xff0c;当然这个指向是绝大多数的IP的出口网关。 ip route add default gw 20.0.0.…

iptables:tproxy做透明代理

什么是透明代理 客户端向真实服务器发起连接&#xff0c;代理机冒充服务器与客户端建立连接&#xff0c;并以客户端ip与真实服务器建立连接进行代理转发。因此对于客户端与服务器来说&#xff0c;代理机都是透明的。 如何建立透明代理 本地socket捕获数据包 nat方式 iptables…

编译参数(-D)

程序中可以使用#ifdef来控制输出信息 #include<stdio.h> #define DEBUGint main() {int a 10;int b 20;int sum a b; #ifdef DEBUGprintf("%d %d %d\n",a,b,sum); #endifreturn 0; } 这样在有宏定义DEBGU的时候就会有信息输出 如果注销掉宏定义就不会有输…

libpcap讲解与API接口函数讲解

ibpcap&#xff08;Packet Capture Library&#xff09;&#xff0c;即数据包捕获函数库&#xff0c;是Unix/Linux平台下的网络数据包捕获函数库。它是一个独立于系统的用户层包捕获的API接口&#xff0c;为底层网络监测提供了一个可移植的框架。 一、libpcap工作原理 libpcap…

Linux常用命令(三)

man 查看帮助文档 alias ls : 查看命令是否被封装 echo &#xff1a; 显示字符串到屏幕终端 echo $PATH : 将环境变量打印出来 poweroff&#xff1a;关机 rebot&#xff1a;重启 需要管理员权限 vim是从vi发展过来的文本编辑器 命令模式&#xff1a;打开文件之后默认进入命令模…

浅谈iptables防SYN Flood攻击和CC攻击

何为syn flood攻击&#xff1a; SYN Flood是一种广为人知的DoS&#xff08;拒绝服务攻击&#xff09;是DDoS&#xff08;分布式拒绝服务攻击&#xff09;的方式之一&#xff0c;这是一种利用TCP协议缺陷&#xff0c;发送大量伪造的TCP连接请求&#xff0c;从而使得被攻击方资源…

Linux之静态库

命名规则&#xff1a; lib 库的名字 .a 制作步骤 生成对应.o文件 .c .o 将生成的.o文件打包 ar rcs 静态库的名字&#xff08;libMytest.a&#xff09; 生成的所有的.o 发布和使用静态库&#xff1a; 1&#xff09; 发布静态 2&#xff09; 头文件 文件如下图所示&…

iptables详解和练习

防火墙&#xff0c;其实说白了讲&#xff0c;就是用于实现Linux下访问控制的功能的&#xff0c;它分为硬件的或者软件的防火墙两种。无论是在哪个网络中&#xff0c;防火墙工作的地方一定是在网络的边缘。而我们的任务就是需要去定义到底防火墙如何工作&#xff0c;这就是防火墙…

Linux之动态库

命令规则 lib 名字 .so 制作步骤 1&#xff09;生成与位置无关的代码&#xff08;生成与位置无关的代码&#xff09; 2&#xff09;将.o打包成共享库&#xff08;动态库&#xff09; 发布和使用共享库 动态库运行原理&#xff1a; 生成动态库&#xff1a; gcc -fPIC -c *.c -…

linux下源码安装vsftpd-3.0.2

1&#xff09;在http://vsftpd.beasts.org/网站中查找并下载 vsftpd-3.0.2.tar.gz源码包 2)如果自己的机器上安装有yum可以用yum grouplist | less指令查看以下开发环境&#xff0c;当然这一步不做也行 3&#xff09;拆解源码包 4&#xff09;查看源码包 5&#xff09;编辑…

Linux之GDB调试命令

gdb启动 gdb 程序名 l 查看源代码&#xff08;默认显示十行&#xff09; l 文件名&#xff1a;行数 l 文件名&#xff1a;函数名 添加断点 break 行数 &#xff08;b 也行&#xff09; b 15 if i 15 条件断点 i b 查看断点信息 start 程序执行一步 n 单步调试 s 单步&#xf…

Gdb 调试core文件详解

一&#xff0c;什么是coredump 我们经常听到大家说到程序core掉了&#xff0c;需要定位解决&#xff0c;这里说的大部分是指对应程序由于各种异常或者bug导致在运行过程中异常退出或者中止&#xff0c;并且在满足一定条件下&#xff08;这里为什么说需要满足一定的条件呢&#…

Linux之GDB命令(二)

gdb命令&#xff1a; 前提条件&#xff1a;可执行文件必须包含调试信息 gcc -ggdb 文件名 –启动gdb调试查看代码命令 当前文件&#xff1a; list 行号&#xff08;函数名&#xff09; 指定文件&#xff1a; list 文件名&#xff1a;行号&#xff08;函数名&#x…

Windows下编译openssl库

1、概述 OpenSSL是一个开放源代码的软件库包&#xff0c;它实现了 SSL&#xff08;Secure SocketLayer&#xff09;和 TLS&#xff08;Transport Layer Security&#xff09;协议&#xff0c;所以应用程序可以使用这个包来进行安全通信&#xff0c;避免窃听&#xff0c;同时确…

Makefile规则介绍

Makefile 一个规则 三要素&#xff1a;目标&#xff0c;依赖&#xff0c;命令 目标&#xff1a;依赖命令 1、第一条规则是用来生成终极目标的规则 如果规则中的依赖不存在&#xff0c;向下寻找其他的规则 更新机制&#xff1a;比较的是目标文件和依赖文件的时间 两个函…