您的位置:首页 > 编程语言

Socket编程实现文件的传输

2017-06-15 19:25 441 查看
客户端执行方式:

./a.out src

其中src代表要进行传输的源文件,目标文件会在服务器端自动生成一个文件,并将客户端传送过来的src文件内容全部写入到服务器所建立的文件中;可以通过md5sum +文件名 的方式来查看src文件和服务器端中生成的文件的内容是否相等;

客户端:

/*************************************************************************
* File Name: client.c
* Author:    The answer
* Function:  Other
* Mail:      2412799512@qq.com
* Created Time: 2017年06月15日 星期四 18时54分22秒
************************************************************************/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<errno.h>
#define MAXSIZE 4096
#define IP "127.0.0.1"
#define SERV_PORT 8000

void sys_err(const char *ptr,int num)
{
perror(ptr);
exit(num);
}

int main(int argc,char **argv)
{
// ./a.out src
int sockfd;
char buf[MAXSIZE];
struct sockaddr_in addr;

//建立socket套接字
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd < 0)
sys_err("socket",-1);

bzero(&addr,sizeof(addr));

//初始化ip+port
addr.sin_family = AF_INET;
addr.sin_port = htons(SERV_PORT);
addr.sin_addr.s_addr = inet_addr(IP);

//connect将sockfd套接字描述符与服务器端的ip+port联系起来
if(connect(sockfd,(struct sockaddr *)&addr,sizeof(addr)) < 0)
sys_err("connect",-2);

//打开读的文件
const char *src = argv[1];
int fd = open(src,O_RDONLY);
if(fd < 0)
sys_err("open",-3);

while(1)
{
int len = read(fd,buf,sizeof(buf));
if(len == 0)
break;

int _tmp = 0;
//考虑若socket缓冲区小于len的情况,见原理图1
while(1)
{
int ret = write(sockfd,buf + _tmp, len - _tmp);
if(ret > 0 )
_tmp += ret;
if(_tmp == ret)
break;
if(ret < 0)
{
perror("write");
break;
}
}

}

close(sockfd);
return 0;
}




图1


服务端:

/*************************************************************************
* File Name: server.c
* Author:    The answer
* Function:  Other
* Mail:      2412799512@qq.com
* Created Time: 2017年06月15日 星期四 17时02分26秒
************************************************************************/

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

//封装出错函数
void sys_err(const char *ptr,int num)
{
perror(ptr);
exit(num);
}

int main(int argc,char **argv)
{
signal(SIGPIPE,SIG_IGN);
int sockfd,accefd;
struct sockaddr_in seraddr,cliaddr;
socklen_t len;

bzero(&seraddr,sizeof(seraddr));
bzero(&cliaddr,sizeof(cliaddr));

//socket
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd < 0)
{
sys_err("socket",-1);
}

//初始化ip地址+port端口号
seraddr.sin_family = AF_INET;
seraddr.sin_port = htons(SERV_PORT);
seraddr.sin_addr.s_addr = htonl(INADDR_ANY);

//bind
if(bind(sockfd,(struct sockaddr *)&seraddr,sizeof(seraddr)) < 0)
{
sys_err("bind",-2);
}

//listen
if(listen(sockfd,128) < 0 )
{
sys_err("listen",-3);
}
//accept
while(1)
{
char buf[4096];
len = sizeof(cliaddr);
accefd = accept(sockfd,(struct sockaddr *)&cliaddr,&len);
if(accefd < 0)
{
if(errno == EINTR)  //判断阻塞等待客户端的链接;是被信号打断还是其它因素
continue;
else
sys_err("accept",-4);
}
//开始文件的读写操作
memset(buf,0x00,sizeof(buf));
int filefd = open("copy.txt",O_WRONLY |O_CREAT |O_TRUNC,0777);
while(1)
{
if(filefd < 0)
sys_err("open",-5);

int leng = read(accefd,buf,sizeof(buf));
if(leng == 0)
{
printf("Opposite have close the socket.\n");
break; //表示文件已经读到了结尾,也意味着客户端关闭了socket
}
if(leng == -1 && errno == EINTR)
continue;
if(leng == -1 )
break; //表示出现了严重的错误
write(filefd,buf,leng);

}

//若文件的读写已经结束,则关闭文件描述符
close(filefd);
close(accefd);
}
close(sockfd);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐