适合新手的网络编程,用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是完全在内核中完成数据传输的,因此避免了用户缓冲区和系统缓冲区的拷贝,因此效率很高。(也就是零拷贝)
#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是完全在内核中完成数据传输的,因此避免了用户缓冲区和系统缓冲区的拷贝,因此效率很高。(也就是零拷贝)
相关文章推荐
- HTTP/2 与 WEB 性能优化(三)
- HTTP/2 与 WEB 性能优化(二)
- HTTP/2 与 WEB 性能优化(一)
- 贝叶斯网络
- 【转载】TCP TIME_WAIT详解
- delphi请求idhttp数据
- window环境下的ip网络释放和重新连接
- 计算机网络- 可靠数据传输协议-设计和实施的协议,如停止的
- 通达OA 小飞鱼老师OA工作流设计课程教学网络公开课之HTML基础(二)
- 通达OA 小飞鱼老师OA工作流设计课程教学网络公开课之HTML基础(二)
- 读书笔记之TCP/IP1(2)
- HTTP 错误 500.19 - Internal Server Error
- 未能从程序集“System.ServiceModel, Version=3.0.0.0”中加载类型“System.ServiceModel.Activation.HttpModule” 的解决办法
- win8 IIS HTTP 错误 404.17 - Not Found
- TCP编程步骤概述
- 关于APP里分享到社交网络的功能介绍
- poj 1637 Sightseeing tour 【网络流 求解混合欧拉回路是否存在】
- Unity中的网络编程
- 以身说法——卓天网络教你为什么做全网营销,怎么做好全网营销
- VIEWGOOD(远古)为您解读时移网络电视台的架设