北城半夏4806197 的學生作業(yè):
file_transfer.c
#include"file_transfer.h"
#include"debug.h"
//接收協(xié)議頭
int recv_protocol_head(int cfd,file_protocol_t *p_head)
{
ssize_t rbytes;
ssize_t total_received = 0;
char *buffer = (char *)p_head;// 按照字節(jié)流接收
// 進行循環(huán)接收,防止 tcp 粘包
for(;;){
//接收數(shù)據(jù)
rbytes = tcp_recv_pack(cfd,buffer + total_received,sizeof(file_protocol_t) - total_received);
if (rbytes == -1){
DEBUG_INFO("[ERROR]: %s ",strerror(errno));
return -1;
}else if (rbytes == 0){
DEBUG_INFO("[INFO] : The client has been shut down.\n");
break;
}else if (rbytes > 0){
total_received += rbytes;
if (total_received == sizeof(file_protocol_t)) // 接收固定長度的數(shù)據(jù)
break;
}
}
if (total_received != sizeof(file_protocol_t)){
DEBUG_INFO("[ERROR] : Failed to receive data.\n");
return -1;
}
return 0;
}
//接收文件數(shù)據(jù)
int recv_filedata(int cfd,const char *filename,size_t targetsize)
{
int fd;
ssize_t rbytes = 0,wbytes = 0,file_size = 0;
char buffer[1024] = {0};
DEBUG_INFO("[INFO] : filename %s\n",filename);
fd = open(filename,O_WRONLY|O_CREAT|O_TRUNC,0666);
if (fd == -1){
DEBUG_INFO("[ERROR] Failed to open filename.\n");
return -1;
}
for(;;){
rbytes = tcp_recv_pack(cfd,buffer,sizeof(buffer));
if (rbytes == -1){
DEBUG_INFO("[ERROR]: %s ",strerror(errno));
return -1;
}else if (rbytes == 0){
DEBUG_INFO("[INFO] : The client has been shut down.\n");
break;
}else if (rbytes > 0){
wbytes = write(fd,buffer,rbytes);
if (wbytes != rbytes){
DEBUG_INFO("[ERROR] : Failed to write data.\n");
return -1;
}
file_size += rbytes;
if (file_size == targetsize)
break;
}
}
close(fd);
return file_size;
}
//文件上傳接口
int client_upload_file(int cfd)
{
int ret;
char *filename;
size_t filesize = 0,recvsize = 0;
file_protocol_t head;
ret = recv_protocol_head(cfd,&head);
if (ret == -1)
return -1;
filename = head.filename;
filesize = head.filesize;
recvsize = recv_filedata(cfd,filename,filesize);
printf("Recv %%%d\n",(int)(recvsize * 1.0 / filesize) * 100);
return recvsize;
}
//協(xié)議頭 發(fā)送接口
int send_protocol_head(const char *filename,int sockfd)
{
int fd;
int filesize;
int ret;
file_protocol_t head;
fd = open(filename,O_RDONLY);
if (fd == -1){
DEBUG_INFO("[ERROR] Failed to open filename.\n");
return -1;
}
filesize = lseek(fd,0,SEEK_END);
close(fd);
head.filesize = filesize;
strcpy(head.filename,filename);
ret = tcp_send_pack(sockfd,&head,sizeof(head));
if (ret != sizeof(file_protocol_t)){
DEBUG_INFO("[ERROR] Failed to send protocol head.\n");
return -1;
}
return filesize;
}
//文件上傳發(fā)送
int upload_file(const char *filename,int sockfd)
{
int file_size,upload_size;
int fd;
ssize_t rbytes = 0,sbytes = 0;
char buffer[1024] = {0};
file_size = send_protocol_head(filename,sockfd);
if (file_size < 0){
return -1;
}
fd = open(filename,O_RDONLY);
if (fd == -1){
DEBUG_INFO("[ERROR] Failed to open filename.\n");
return -1;
}
for(;;){
rbytes = read(fd,buffer,sizeof(buffer));
if (rbytes == -1){
DEBUG_INFO("[ERROR] Failed to read data.\n");
return -1;
}
sbytes = tcp_send_pack(sockfd,buffer,rbytes);
if (sbytes != rbytes){
DEBUG_INFO("[ERROR] Failed to send data.\n");
return -1;
}
upload_size += rbytes;
}
close(fd);
return upload_size;
}
file_transfer.h
#ifndef __FILE_TRANSFER_H_
#define __FILE_TRANSFER_H
#include "tcp_socket.h"
#include
#include
#include
#define FILENAME_SZ 256
typedef struct file_protocol{
size_t filesize; // 文件大小
char filename[FILENAME_SZ]; // 文件名
}file_protocol_t;
extern int recv_protocol_head(int cfd,file_protocol_t *p_head);
extern int recv_filedata(int cfd,const char *filename,size_t targetsize);
extern int client_upload_file(int cfd);
extern int send_protocol_head(const char *filename,int sockfd);
extern int upload_file(const char *filename,int sockfd);
#endif