linux高级I/O函数(2)——sendfile和splice

1、sendfile和splice相同之处

sendfile和splice这两个函数都是在文件描述符之间传输数据的,而且两者都是“零拷贝”,数据不需要内核空间和用户空间直接做无谓的复制,区别在于,
sendfile函数的两个文件描述符参数out_fd必须为socket,
而splice函数的两个文件描述符参数必须有一个是管道

#include<sys/sendfile.h>
ssize_t senfile(int out_fd,int in_fd,off_t* offset,size_t count);

#include <fcntl.h>
ssize_t splice(int fdin, loff_t *offin, int fdout, loff_t *offout, size_t len, unsigned int flags);
2、下面用两个函数写个简单例子

用sendfile将文件的内容通过服务器发送给连接上的客户端。
用splice函数写一个简单的回射服务器(将客户端的数据返回给客户端)。

3、sendfile
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <poll.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/sendfile.h>
#include <sys/stat.h>

/*sendfile 将文件内的数据发送给连接上的客户端*/

const int  g_port = 10086;
const char* file_name = "test.txt";

int main(void)
{
	int filefd = open(file_name, O_RDONLY);
	if (filefd < 0) {
		printf("open err\n");
		return -1;
	}
	/*int fstat(int fdp, struct stat *struct_stat);  //通过文件描述符获取文件对应的属性。fdp为文件描述符

下面是这个结构的结构
struct stat {
        mode_t     st_mode;       //文件对应的模式,文件,目录等
        ino_t      st_ino;       //inode节点号
        dev_t      st_dev;        //设备号码
        dev_t      st_rdev;       //特殊设备号码
        nlink_t    st_nlink;      //文件的连接数
        uid_t      st_uid;        //文件所有者
        gid_t      st_gid;        //文件所有者对应的组
        off_t      st_size;       //普通文件,对应的文件字节数
	    ime_t     st_atime;      //文件最后被访问的时间
        time_t     st_mtime;      //文件内容最后被修改的时间
        time_t     st_ctime;      //文件状态改变时间
        blksize_t st_blksize;    //文件内容对应的块大小
        blkcnt_t   st_blocks;     //伟建内容对应的块数量
      };*/
	struct stat stat_buf;
	fstat(filefd, &stat_buf);

	struct sockaddr_in addr_server;
	bzero(&addr_server, sizeof(addr_server));
	addr_server.sin_family = AF_INET;
	addr_server.sin_port = htons(g_port);
	addr_server.sin_addr.s_addr = htonl(INADDR_ANY);

	int sfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sfd < 0) {
		printf("socket err \n");
		return -1;
	}
	int ret = bind(sfd, (struct sockaddr*)&addr_server, sizeof(addr_server));
	if (ret < 0) {
		printf("binf err \n");
		return -1;
	}

	ret = listen(sfd, 10);
	if (ret < 0) {
		printf("listen err\n");
		return -1;
	}
	struct sockaddr_in addr_client;
	socklen_t addrlen_client = sizeof(addr_client);
	//bzero(&addr_client, addrlen_client);

	int cfd = accept(sfd, (struct sockaddr*)&addr_client, &addrlen_client);
	if (cfd < 0) {
		printf("accept err \n");
		return -1;
	}
	else
	{
		/*出现了*/
		/*#include<sys/sendfile.h>	
		ssize_t senfile(int out_fd,int in_fd,off_t* offset,size_t count);*/
		sendfile(cfd, filefd, NULL, stat_buf.st_size);
		close(cfd);
	}
	close(sfd);
	return 0;
}
4、splice
#define _GNU_SOURCE 1

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>


/*splice 实现的回射服务器*/

const int  g_port = 10086;


int main(void)
{
	int ret = 0;
	struct sockaddr_in addr_server;
	bzero(&addr_server, sizeof(addr_server));
	addr_server.sin_family = AF_INET;
	addr_server.sin_port = htons(g_port);
	addr_server.sin_addr.s_addr = htonl(INADDR_ANY);

	int sfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sfd < 0) {
		printf("socket err \n");
		return -1;
	}
	ret = bind(sfd, (struct sockaddr*)&addr_server, sizeof(addr_server));
	if (ret < 0) {
		printf("binf err \n");
		return -1;
	}

	ret = listen(sfd, 10);
	if (ret < 0) {
		printf("listen err\n");
		return -1;
	}
	struct sockaddr_in addr_client;
	socklen_t addrlen_client = sizeof(addr_client);
	//bzero(&addr_client, addrlen_client);

	int cfd = accept(sfd, (struct sockaddr*)&addr_client, &addrlen_client);
	if (cfd < 0) {
		printf("accept err \n");
		return -1;
	}
	else
	{
		int pipefd[2];
		ret = pipe(pipefd);
		if (ret < 0) {
			printf("pipe err \n");
			return -1;
		}
		ret = splice(cfd, NULL, pipefd[1], NULL, 1024, SPLICE_F_MORE | SPLICE_F_MOVE);
		if (ret < 0) {
			printf("splice1 err\n");
			return -1;
		}
		ret = splice(pipefd[0], NULL, cfd, NULL, 1024, SPLICE_F_MORE | SPLICE_F_MOVE);
		if (ret < 0) {
			printf("splice2 err\n");
			return -1;
		}
		close(cfd);
	}
	close(sfd);
	return 0;
}
发布了46 篇原创文章 · 获赞 13 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_42718004/article/details/90756348