您的位置:首页 > 理论基础 > 计算机网络

适合新手的网络编程,用socket传文件(本例传的是jpg图片) 用到sendfile函数

2015-09-09 09:34 681 查看
服务器端代码:用来接受客户端发来的文件

#include<sys/socket.h>

#include<netinet/in.h>

#include<arpa/inet.h>

#include<assert.h>

#include<stdio.h>

#include<stdlib.h>

#include<errno.h>

#include<string.h>

int main(int argc,char* argv[])

{
assert(argc>2);
FILE *filefd=fopen("a.jpg","ab");
struct sockaddr_in address;
address.sin_family=AF_INET;
inet_pton(AF_INET,argv[1],&address.sin_addr);
address.sin_port=htons(atoi(argv[2]));
int sockfd=socket(PF_INET,SOCK_STREAM,0);
assert(sockfd!=0);
int ret=bind(sockfd,(struct sockaddr*)&address,sizeof(address));
assert(ret!=-1);
listen(sockfd,5);
struct sockaddr_in client;
size_t clientaddrlen=sizeof(client);
int connfd=accept(sockfd,(struct sockaddr*)&client,&clientaddrlen);
assert(connfd>=0);
char buffer[512];
int rn;
while(1)
{
rn=recv(connfd,buffer,512,0);
if(rn<0)
{
printf("接受错误!\n");
close(connfd);
close(sockfd);
return 1;
}
buffer[rn]='\0';
if(rn!=0)
{
fwrite(buffer,1,rn,filefd);
bzero(buffer,sizeof(buffer));
}
else
{
printf("接受完成!\n");
break;
}
}
fclose(filefd);
close(connfd);
close(sockfd);
return 0;

}

客户端代码:使用sendfile函数,先上代码,下面介绍sendfile的用法

#include<stdio.h>

#include<stdlib.h>

#include<netinet/in.h>//定义了主机字节序列和网络字节序列的转换

#include<bits/socket.h>//定义了PF×和AF×

#include<sys/un.h>//定义专用的socket地址

#include<arpa/inet.h>//定义ip地址转换函数

#include<sys/types.h>

#include<sys/socket.h>

#include<unistd.h>

#include<errno.h>

#include<assert.h>

#include<string.h>

#include<string>

#include <iostream>

#include<sys/stat.h>

#include<sys/sendfile.h>

#include<fcntl.h>

using namespace std;

int main(int argc,char* argv[])

{
string str;
if(argc<=2)
{
printf("%s 请输入ip地址和端口号\n",basename(argv[0]));
return 1;
}
const char* ip=argv[1];
int port=atoi(argv[2]);
struct sockaddr_in server_address;
bzero(&server_address,sizeof(server_address));
server_address.sin_family=AF_INET;
server_address.sin_port=htons(port);
inet_pton(AF_INET,ip,&server_address.sin_addr);
int sock=socket(PF_INET,SOCK_STREAM,0);
assert(socket>=0);
int fd=open("a.jpg",O_RDONLY);
assert(fd>0);
struct stat stat_buf;
fstat(fd,&stat_buf);
if(connect(sock,(struct sockaddr*)&server_address,sizeof(server_address))<0)
{
cout<<errno<<endl;
}
else
{
sendfile(sock,fd,NULL,stat_buf.st_size);
}
close(sock);
return 0;

}

sendfile函数:

是linux中的系统调用,和open函数一样(服务器端的fopen则是c库函数),因此这个简单的程序是不能

跨平台的,只能在linux(我的是ubuntu)下运行(从头文件也可以看到很多的linux的库)。

#include<sys/sendfile.h>

ssize_t sendfile(int out_fd,int in_fd,off_t* offset,size_t count);

其中in_fd必须是具体的文件,不能是socket和管道,

out_fd必须是socket,

offset是指从文件的什么位置开始传,(NULL是指文件的开始位置)

count是指传多长(通常通过stat来获取文件的长度)

由参数也可以看出sendfile是专门为网络传输定制的。

sendfile是完全在内核中完成数据传输的,因此避免了用户缓冲区和系统缓冲区的拷贝,因此效率很高。(也就是零拷贝)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: