spilce可以实现在两个文件描述符间零拷贝。
有两个需要注意的点:
1.如果输入的文件描述符是管道,则偏移量必须为NULL
2.splice的输入和输出中必有一个文件描述符是管道
回射服务器使用一个管道,管道的两端全连接到客户端的文件描述符,这样客户端输出的数据直接从管道再流回去。
代码:
服务器
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<assert.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/sendfile.h>
int main(int argc, char* argv[]){
if(argc < 3){
printf("ip port and filename \n");
return 0;
}
char* ip = argv[1];
int port = atoi(argv[2]);
char* filename = argv[3];
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
bzero(&addr, sizeof(addr));
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
inet_pton(AF_INET, ip, &addr.sin_addr);
int ret = bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));
assert(ret != -1);
ret = listen(sockfd, 5);
assert(ret != -1);
struct sockaddr_in caddr;//客户端地址
socklen_t caddr_len;
int connfd = accept(sockfd, (struct sockaddr*)&caddr, &caddr_len);
if(connfd < 0){
printf("connect failure \n");
}else{
int pipefd[2];
ret = pipe(pipefd);
assert(ret != -1);
ret = splice(connfd, NULL, pipefd[1], NULL, 32768, SPLICE_F_MORE);
assert(ret != -1);
ret = splice(pipefd[0], NULL, connfd, NULL, 32768, SPLICE_F_MORE);
assert(ret != -1);
close(connfd);
}
close(sockfd);
return 0;
}
客户端
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<assert.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#define BUFFER_SIZE 1024
int main(int argc, char* argv[]){
if(argc <= 3){
printf("ip and port and size!!!\n");
return 0;
}
char* ip = argv[1];
int port = atoi(argv[2]);
char* str = argv[3];
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serveraddr;
bzero(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(port);
inet_pton(AF_INET, ip, &serveraddr.sin_addr);
if((connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr))) < 0){
printf("connect failure \n");
}else{
printf("%d %s",strlen(str), str); //这里不能用sizeof,sizeof的结果不对
send(sockfd, str, strlen(str), 0);
char recvbuf[BUFFER_SIZE];
memset(recvbuf, '\0', BUFFER_SIZE);
int ret = recv(sockfd, recvbuf, BUFFER_SIZE - 1, 0);
printf("recieve %d bytes, content is :%s \n", ret, recvbuf);
}
close(sockfd);
return 0;
}
运行效果:
服务器没什么显示效果就不放了
客户端