linux网络编程九:splice函数,高效的零拷贝
from:http://blog.csdn.net/jasonliuvip/article/details/22600569
linux网络编程九:splice函数,高效的零拷贝
最近在看《Linux高性能服务器编程》,在此做个日记,以激励自己,同时分享于有需要的朋友。
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;
- }
linux网络编程九:splice函数,高效的零拷贝的更多相关文章
- linux网络编程:splice函数和tee( )函数高效的零拷贝
splice( )函数 在两个文件描述符之间移动数据,同sendfile( )函数一样,也是零拷贝. 函数原型: #include <fcntl.h> ssize_t splice(int ...
- Linux 网络编程九(select应用--大并发处理)
//网络编程服务端 /* * 备注:因为客户端代码.辅助方法代码和epoll相同,所以select只展示服务器端代码 */ #include <stdio.h> #include < ...
- Linux 网络编程 入门-常用函数
网络连接无外乎服务器和客户端两方面的编程. 对于服务器大致的流程是:1---调用socket函数创建套接字 2---调用bind函数分配IP地址和端口号 3---调用listsen函数将套接字转为可接 ...
- Linux网络编程2——系统函数
socket信息数据结构 #include <netinet/in.h> struct sockaddr { unsigned short sa_family; /*地址族*/ ]; /* ...
- linux网络编程:select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET(转)
从别人的博客中转载过来了这一篇文章,经过重新编辑排版之后展现于此,做一个知识点保存与学习. select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复 ...
- linux网络编程涉及的函数
常用的网络命令: netstat 命令netstat是用来显示网络的连接,路由表和接口统计等网络的信息. netstat有许多的选项我们常用的选项是-an用来显示详细的网络状态.至于其它选项我们使用帮 ...
- linux 网络编程 inet_pton & inet_ntop函数
#include <arpa/inet.h> int inet_pton(int family,const char * strptr,void * addrptr); 返回:--成功, ...
- 【深入浅出Linux网络编程】 "开篇 -- 知其然,知其所以然"
[深入浅出Linux网络编程]是一个连载博客,内容源于本人的工作经验,旨在给读者提供靠谱高效的学习途径,不必在零散的互联网资源中浪费精力,快速的掌握Linux网络编程. 连载包含4篇,会陆续编写发出, ...
- Linux网络编程入门 (转载)
(一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...
随机推荐
- Online ddl 思维导图
http://blog.itpub.net/22664653/viewspace-2056953/ 整理一份 MySQL DDL 的思维导图,介绍5.5版本以及之前 和 5.6 版本的 MySQL ...
- ireport启动闪退问题
安装好ireport之后,双击ireport.exe启动程序只是掠过启动画面便毫无反应, 后来在网上找了下解决方法,才知道只因为ireport与jdk8不兼容, 于是下载了jdk6,并在ireport ...
- mysql 日期函数格式
mysql中的from_unixtime函数的format表达式字段描述: %M 月名字(January……December) %W 星期名字(Sunday……Saturday) %D 有英语前缀的 ...
- BEA WebLogic Server 10 查看和配置日志
查看和配置日志 WebLogic Server 内的每个子系统都可生成日志消息来传达其状态.例如,当启动 WebLogic Server 实例时,安全子系统会输出消息以报告其初始化状态.为了记录其子系 ...
- Windows 之 删除文件出现“该项目不在请确认该项目的位置”
原理为通过 DOS 命令自建一个 .bat 批处理文件. 第一步,首先桌面新建TXT文档: 第二步,主要使用DEL 和 RD 命令,打开文档复制下面内容里面: DEL /F /A /Q \\?\%1 ...
- Eclipse开发JQuery环境设置(Spket)
http://www.cnblogs.com/sayo/archive/2008/10/20/1315528.html 首先需要安装Spket.可以参阅我的这篇文章进行Spket的安装. 之后进 ...
- eclipse按Crl+鼠标左键,找不到源文件的解决办法。
这种情况一般发生在tomcat的之中,原因是缺少类的源文件.在jdk中很少见,jdk中自带类的源文件,配置jdk的时候就已经将其加载进来了.而tomcat之中没有带类的源文件,需要自己去网上单独下载. ...
- DOM+Javascript一些实例
1.内容+遮罩层+悬浮对话框 <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...
- ubuntu禁用笔记本自带键盘
ubuntu如何禁用笔记本键盘 打开终端运行命令 xinput list Virtual core pointer id=2 [master pointer (3)] ⎜ ↳ Virtual core ...
- Oracle查找被长时间锁定的对象并kill
1.用如下语句查找被锁住的表名.OSclient.Session信息 SELECT B.SID ,B.SERIAL# ,D.SPID OS系统进行号 ...