Linux下基于TCP/IP协议的文件传输程序【设计目的】通过Linux C编程,设计一个基于TCP/IP的文件传输系统,实现网络文件的收发【设计环境】Ubuntu 12.04【设计方案】(1)文件读写任意文件都可以二进制的方式进行读写,为了实现任意文件类型的传输,在读写文件的过程中,必须采用二进制的读写方式。
(2)传输协议为了保证数据的正确性,文件传输需要采用一种可靠的传输协议。
UDP协议实现比较简单,但UDP面向无连接,传输过程中,会出现丢包的情况,导致数据发送失败。
故采用面向连接的TCP/IP协议,防止传输过程中的数据丢失的情况。
(3)大文件的传输对于比较大的文件,应该进行分包操作,以防止占用过多的内存,导致文件发送失败。
【设计流程】如图1所示,服务器程序作为文件的发送方。
首先,服务器端输入要发送的文件。
然后,创建一个流式套接字(SOCK_STREAM),进行绑定。
绑定成功后,执行监听,当有客户发送连接请求,执行Accept(),接收来自客户端的请求。
连接建立后,首先服务器向客服端发送的文件的文件名及扩展名等信息。
信息发送完毕,服务器方将待发送的数据读入缓冲区,通过套接字将数据发送出去。
发送完成后退出,并显示发送完成的信息。
图1 服务器流程图如图2所示,客户端程序完成文件的接收操作。
首先,创建一个流式套接字。
套接字创建成功后,对该套接字进行绑定。
绑定成功后,向服务器方发送连接请求。
连接成功后,首先,接收服务器发送的文件信息。
接收成功后,开始数据的接收。
文件接收完毕,显示文件已接收完成。
图2 客户端流程图【设计测试】了验证设计的正确性,在Ubuntu 12.04系统上对可执行文件进行了回环测试。
步骤如下:(1)测试文件a.txt及服务器端文件源fileserver.c和可执行文件fileserver(2)客户端源文件及可执行文件(3)执行服务器端文件fileserver并输入要传输的文件a.txt,等待客户端连接(4)执行客户端文件fileclient,如果不输入IP地址将显示提示(5)执行客户端文件后,输入完整命令,文件传输文件完成(6)看到服务器端也显示文件传输完成服务器源码:#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/socket.h>#include <netinet/in.h>#define PORT 6000#define LISTENQ 20#define BUFFSIZE 4096#define FILE_NAME_MAX_SIZE 512int main(int argc, char **argv[]){//输入文件名称char filename[FILE_NAME_MAX_SIZE];bzero(filename,FILE_NAME_MAX_SIZE);printf("Please input the file name you wana to send:");scanf("%s",&filename);getchar();//设置一个socket地址结构int sockfd,connfd;struct sockaddr_in svraddr,clientaddr;bzero(&svraddr,sizeof(svraddr));//把一段内存区的内容全部设置为0svraddr.sin_family=AF_INET;svraddr.sin_addr.s_addr=htonl(INADDR_ANY);svraddr.sin_port=htons(PORT);//创建用于internet的流协议(TCP)socketsockfd=socket(AF_INET,SOCK_STREAM,0);if(sockfd<0){perror("socket");exit(1);}//把socket和socket地址结构绑定if(bind(sockfd,(struct sockaddr*)&svraddr,sizeof(svraddr))<0){perror("bind");exit(1);}//监听if(listen(sockfd,LISTENQ)<0){perror("listen");exit(1);}while(1)//服务器端一直运行{socklen_t length=sizeof(clientaddr);//等待请求connfd=accept(sockfd,(struct sockaddr*)&clientaddr,&length);if(connfd<0){perror("connect");exit(1);}//发送文件信息char buff[BUFFSIZE];int count;bzero(buff,BUFFSIZE);strncpy(buff,filename,strlen(filename)>FILE_NAME_MAX_SIZE?FILE_NAME_MAX_SIZE:st rlen(filename));count=send(connfd,buff,BUFFSIZE,0);if(count<0){perror("Send file imformation");exit(1);}//读取文件并发送文件FILE *fd=fopen(filename,"rb");if(fd==NULL){printf("File :%s not found!\n",filename);}else{bzero(buff,BUFFSIZE);int file_block_length=0;while((file_block_length=fread(buff,sizeof(char),BUFFSIZE,fd))>0){printf("file_block_length:%d\n",file_block_length);if(send(connfd,buff,file_block_length,0)<0){perror("Send");exit(1);}bzero(buff,BUFFSIZE);}fclose(fd);printf("Transfer file finished !\n");}close(connfd);}close(sockfd);//关闭socketreturn 0;}客户端源码:#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/socket.h>#include <netinet/in.h>#define PORT 6000#define LISTENQ 20#define BUFFSIZE 4096#define FILE_NAME_MAX_SIZE 512int main(int argc, char **argv[]){int clientfd;if(argc!=2)//判断参数是否完整{fprintf(stderr,"Usage:./fileclient <IP_Address>\n");exit(1);}struct sockaddr_in clientaddr;bzero(&clientaddr,sizeof(clientaddr));clientaddr.sin_family=AF_INET;clientaddr.sin_addr.s_addr=htons(INADDR_ANY);//INADDR_ANY表示自动获取本机地址clientaddr.sin_port=htons(0); //0表示让系统自动分配一个空闲端口//创建用于internet的流协议(TCP)socket,用clientfd代表客户机socketclientfd=socket(AF_INET,SOCK_STREAM,0);if(clientfd<0){perror("socket");exit(1);}//把客户机的socket和客户机的socket地址结构联系起来if(bind(clientfd,(struct sockaddr*)&clientaddr,sizeof(clientaddr))<0){perror("bind");exit(1);}//设置一个socket地址结构体struct sockaddr_in svraddr;bzero(&svraddr,sizeof(svraddr));if(inet_aton(argv[1],&svraddr.sin_addr)==0)//IP地址来自程序的参数{perror("inet_aton");exit(1);}svraddr.sin_family=AF_INET;svraddr.sin_port=htons(PORT);socklen_t svraddrlen=sizeof(svraddr);//向服务器发起连接,连接成功后client_socket代表了客户机和服务器的一个socket 连接if(connect(clientfd,(struct sockaddr*)&svraddr,svraddrlen)<0){perror("connect");exit(1);}//接收文件信息char buff[BUFFSIZE];char filename[FILE_NAME_MAX_SIZE];bzero(filename, FILE_NAME_MAX_SIZE);int count;bzero(buff,BUFFSIZE);count=recv(clientfd,buff,BUFFSIZE,0);if(count<0){perror("recv");exit(1);}strncpy(filename,buff,strlen(buff)>FILE_NAME_MAX_SIZE?FILE_NAME_MAX_SIZE:strlen( buff));printf("Preparing recv file : %s---from---%s \n",filename,argv[1]);//接收文件FILE *fd=fopen(filename,"wb+");if(NULL==fd){perror("open");exit(1);}bzero(buff,BUFFSIZE);int length=0;while(length=recv(clientfd,buff,BUFFSIZE,0)){if(length<0){perror("recv");exit(1);}int writelen=fwrite(buff,sizeof(char),length,fd);if(writelen<length){perror("write");exit(1);}bzero(buff,BUFFSIZE);}printf("Receieved file:%s from %s finished!\n",filename,argv[1]);fclose(fd);close(clientfd); //关闭socketreturn 0;}。