Linux下用UDP实现文件传输

原文:https://blog.csdn.net/li_k_y/article/details/83412643

UDP编程框图

                                         

        UDP协议中服务器和客户端的交互存在于数据的收发过程中。

        进行网络数据收发的时候,服务器和客户端的数据是对应的:客户端发送数据的动作,对服务器来说是接收数据的动作;客户端接收数据的动作,对服务器来说是发送数据的动作。

     实现文件的传输大概分为这几个步骤:

  1. 客户端读文件,将内容放在client_buffer中
  2. 客户端通过sendto发送client_buffer中的数据
  3. 服务器端通过recvfrom对数据进行接收,存到server_buffer中
  4. 将数据写入文件中,关闭文件,关闭套接字

直接来代码:

服务器端:
 

// udp_file_server.c
 
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <netinet/in.h>
#include <errno.h>
#include <memory.h> 
#include <stdlib.h> 
 
#define BUFFER_SIZE 1024
 
int main()
{
    int sockfd,n;
    struct sockaddr_in server,client;
	int addrlen=sizeof(struct sockaddr);
    char filename[100];
    char filepath[100];
 
    char *buffer;//file buffer
    int fileTrans;
 
    buffer = (char *)malloc(sizeof(char)*BUFFER_SIZE);
    printf("init bufferSize=%d  SIZE=%d\n",sizeof(buffer),BUFFER_SIZE);
    bzero(buffer,BUFFER_SIZE); 
    int lenfilepath;
    FILE *fp;
    int writelength;
 
    if((sockfd = socket(AF_INET,SOCK_DGRAM,0))<0)
    {
        printf("socket build error!\n");
    }
    else
    {
        printf("socket build success!\n");
    }
    memset(&server,0,sizeof(server));  //清空server结构体
    server.sin_family= AF_INET;
    server.sin_addr.s_addr = htonl(INADDR_ANY);
    server.sin_port = htons(8888);
 
    if((bind(sockfd,(struct sockaddr*)&server,sizeof(server)))==-1)
    {
        printf("bind error!\n");
    }
    else
    {
        printf("bind success!\n");
    }
    
    while(1)
    {
	    printf("waiting....\n");
            memset(filename,'\0',sizeof(filename));
            memset(filepath,'\0',sizeof(filepath));
            lenfilepath = recvfrom(sockfd,filepath,100,0,(struct sockaddr *)&client,&addrlen);
            printf("filepath :%s\n",filepath);
            if(lenfilepath<0)
            {
                printf("recv error!\n");
				return -1;
            }
            else
            {
                int i=0,k=0;  
                for(i=strlen(filepath);i>=0;i--)  
                {  
                    if(filepath[i]!='/')      
                    {  
                        k++;  
                    }  
                    else   
                        break;    
                }  
                strcpy(filename,filepath+(strlen(filepath)-k)+1);   
            }
            printf("filename :%s\n",filename);
            fp = fopen(filename,"w");
            if(fp!=NULL)
            {
		int times = 1;
                while(fileTrans =recvfrom(sockfd,buffer,BUFFER_SIZE,0,(struct sockaddr *)&client,&addrlen))
                {
			printf("times = %d   ",times);
			times++;
                    if(fileTrans<0)
                    {
                        printf("recv2 error!\n");
                        break;
                    }
 
                    writelength = fwrite(buffer,sizeof(char),fileTrans,fp);
 
                    if(fileTrans < BUFFER_SIZE)
                    {
                        printf("finish writing!\n");
                        break;
                    }else{
			//printf("write succ! %d fileTrans=%d\n",writelength,fileTrans);
			printf("write successful!\n");
			//break;
		    }
		printf("continue\n");
                    bzero(buffer,BUFFER_SIZE); 
                }
                printf("recv finished!\n");
                fclose(fp);
            }
            else
            {
                printf("filename is null!\n");
 
            }
    }
    close(sockfd);
    return 0;
}

客户端:

//   udp_file_client
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <netinet/in.h>
#include <errno.h>
#include <memory.h> 
#include <stdlib.h>
 
#define BUFFER_SIZE 1024
 
int main()
{
    int sockcd;
    struct sockaddr_in server;
    char filepath[100];//file to translate
    int addrlen=sizeof(struct sockaddr);
 
    FILE *fp;
    int lenpath; //filepath length
    char *buffer;//file buffer
    int fileTrans;
    buffer = (char *)malloc(sizeof(char)*BUFFER_SIZE);
    bzero(buffer,BUFFER_SIZE); 
 
    if((sockcd = socket(AF_INET,SOCK_DGRAM,0))<0)
    {
        printf("socket build error!\n");
    }
    memset(&server,0,sizeof(server));
    server.sin_family= AF_INET;
    server.sin_port = htons(8888);
    if(inet_pton(AF_INET,"127.0.0.1",&server.sin_addr)<0)
    {
        printf("inet_pton error!\n");
    }
 
    printf("file path:\n");
    scanf("%s",filepath);//get filepath
 
    fp = fopen(filepath,"r");//opne file
    if(fp==NULL)
    {
        printf("filepath not found!\n");
        return 0;
 
    }
    printf("filepath : %s\n",filepath);
    lenpath = sendto(sockcd,filepath,strlen(filepath),0,(struct sockaddr *)&server,addrlen);// put file path to sever 
    if(lenpath<0)
    {
        printf("filepath send error!\n");
    }
    else
    {
        printf("filepath send success!\n");
    }
    //sleep(1);
    printf("begin send data...\n");
    int times = 1;
    while((fileTrans = fread(buffer,sizeof(char),BUFFER_SIZE,fp))>0)
    {
	sleep(1);  //注意这里
	printf("times = %d   ",times);
	times++;
        //printf("fileTrans =%d\n",fileTrans);
        if(sendto(sockcd,buffer,fileTrans,0,(struct sockaddr *)&server,addrlen)<0)
        {
            printf("send failed!\n");
            break;      
        }
	else{
	    printf("send successful!\n");
	}
	if(fileTrans < BUFFER_SIZE) break;
        bzero(buffer,BUFFER_SIZE); 
    }
    //printf("fileTrans =%d\n",fileTrans);
    fclose(fp);
    close(sockcd);
    return 0;
}

在实现过程中,出现了这样一种情况:

        在收发大文件时,客户端发送正常,服务器总是只能收到前一部分文件内容,后面的全部丢包。

扫描二维码关注公众号,回复: 5474255 查看本文章

在经过各种调试之后,发现在发数据时,客户端一直在循环不断的发送数据,发送太快,而服务器来不及接收 。

在每次发送数据时,sleep一会,这个问题就解决了。

效果图:

运行......

结果:

猜你喜欢

转载自blog.csdn.net/qq_37990044/article/details/88127222