1.客户端:
客户端程序使用poll同事监听用户输入和网络连接,并利用splice函数将用户输入内容直接定向到网络连接上以发送之,从而实现数据零拷贝,提高了程序执行效率。
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:如果输出是文件,这个值则会使得操作系统内核尝试从输入管道缓冲区直接将数据读入到输出地址空间,这个数据传输过程没有任何数据拷贝操作发生。
使用splice时, fd_in和fd_out中必须至少有一个是管道文件描述符。
调用成功时返回移动的字节数量;它可能返回0,表示没有数据需要移动,这通常发生在从管道中读数据时而该管道没有被写入的时候。
失败时返回-1,并设置errno。
客户端程序如下:poll监听标准输入,直接重定向到sockfd。
/*************************************************************************
> File Name: client.c
> Author: dulun
> Mail: [email protected]
> Created Time: 2016年07月19日 星期二 11时01分09秒
************************************************************************/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<poll.h>
#include<fcntl.h>
#include<assert.h>
#define BUFFER_SIZE 64
int main()
{
const char * ip = "127.0.0.1";
int port = 10086;
struct sockaddr_in server_address;
bzero( &server_address, sizeof(server_address) );
server_address.sin_family = AF_INET;
inet_pton( AF_INET, ip, &server_address.sin_addr );
server_address.sin_port = htons(port);
int sockfd = socket( PF_INET, SOCK_STREAM, 0 );
assert(sockfd >= 0);
if( connect(sockfd, (struct sockaddr*)&server_address, sizeof(server_address)) < 0 )
{
printf("connetcion failed\n");