UDP协议来快速无丢失传输图像程序

以下程序实现了UDP协议下无丢失快速的传输图像数据,测试数据是egtest01图像库,实现了PC和嵌入式端的图像传输,传输+读写的速度可以实现10+M/S,贴上代码可作为参考



服务器端程序

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <errno.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/time.h>

#define DEST_PORT 3000
#define MAX_DATA 51200	//50kb
#define DEST_IP_ADDRESS "10.42.0.1" //"192.168.1.113"//"10.42.0.1" //"192.168.1.19"//"169.254.9.36"

#ifndef bool
#define bool int
#define true 1
#define false 0
#endif

int main(int argc,char* argv[])
{
    int sock_fd;
    int send_num;
    int recv_num;
    int dest_len;
    char send_buf[100];
    char recv_buf[MAX_DATA];
    char recv_path[1024];
    char recv_over[12]="receive over";
    char send_again[18]="send package again";
    struct sockaddr_in addr_serv;
    
    sock_fd=socket(AF_INET,SOCK_DGRAM,0);
    if(sock_fd<0)
    {
        perror("socket error\n");
        exit(1);
    }else
    {
        printf("socket success\n");
    }
  
    memset(&addr_serv,0,sizeof(struct sockaddr_in));
    addr_serv.sin_family=AF_INET;
    addr_serv.sin_port=htons(DEST_PORT);
    addr_serv.sin_addr.s_addr=inet_addr(DEST_IP_ADDRESS);
    
    dest_len=sizeof(struct sockaddr_in);
    
   //设置超时时间
    struct timeval tv_out;
    tv_out.tv_sec=3;
    tv_out.tv_usec=0;
    setsockopt(sock_fd,SOL_SOCKET,SO_RCVTIMEO,&tv_out,sizeof(tv_out));



    printf("begin send\n");
    
    struct timeval tpstart,tpend;
    double timeuse;
    gettimeofday(&tpstart,NULL);
    
    int index=0;
    for(index=0;index<1821;index++)
    {
        sprintf(send_buf,"frame%0.5d.bmp",index);
        send_num=sendto(sock_fd,send_buf,14,0,(struct sockaddr*)&addr_serv,dest_len);
        if(send_num<0)
    	{
       	    perror("send error\n");
       	    exit(1);
    	}else
    	{
            printf("request for %s success\n",send_buf);
    	}
    	
    	//printf("begin receive\n");
    	sprintf(recv_path,"/opt/imagedata/egtest01_bmp/%s",send_buf);
    	FILE *fd=fopen(recv_path,"wb+");
    	
	
	int onums=0;
	while(fd==NULL)
    	{
	    onums++;
            perror("open fail");
            printf("try to open %s for receiving %d\n",recv_path,onums);
            fd=fopen(recv_path,"wb+");
    	    
    	    //exit(1);
    	}
	

        long int position=0;
        unsigned long saposition=0;
        int recv9=0;
        while(1)
        {
            memset(recv_buf,0,sizeof(recv_buf));
    	    recv_num=recvfrom(sock_fd,recv_buf,sizeof(recv_buf),0,(struct sockaddr*)&addr_serv,&dest_len);//MSG_DONTWAIT
            
            //printf("recv_num: %d\n",recv_num);
    	    if(recv_num<0)
    	    {
    	      //perror("receive error");
              fseek(fd,saposition,SEEK_SET);
              position=saposition;
              send_num=sendto(sock_fd,send_again,18,0,(struct sockaddr*)&addr_serv,dest_len);
              continue;
    	    }
            else if(recv_num==9&&(position==921654||recv9>=3))
            {
              fclose(fd);
              break;//接收一个文件结束
            }
            else if(recv_num==51200||recv_num==54)
            {
              //printf("position is in %ld\n",position);
              fseek(fd,position,SEEK_SET);
    	      fwrite(recv_buf,1,recv_num,fd);

	      saposition=position;
    	      position+=recv_num;
              send_num=sendto(sock_fd,recv_over,12,0,(struct sockaddr*)&addr_serv,dest_len);
    	    }
            else
            {
               //printf("recv_num error: %d\n",recv_num);
               recv9++;
	       fseek(fd,saposition,SEEK_SET);
               position=saposition;
               continue;
               //exit(-1);
            }
    	} 

    }
    close(sock_fd);
    
    gettimeofday(&tpend,NULL);
    timeuse=1000*(tpend.tv_sec-tpstart.tv_sec)+(tpend.tv_usec-tpstart.tv_usec)/1000;
  
    printf("processor time is %lf ms\n",timeuse);
    return 0;   
        
}



客户端程序

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <errno.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SERV_PORT 3000
#define MAX_DATA 51200	//50kb
#define FILE_LENGTH 921654 //图片大小

#ifndef bool
#define bool int
#define true 1
#define false 0
#endif

int main(int argc,char* argv[])
{
    int sock_fd;
    int recv_num;
    int send_num;
    int client_len;
    char recv_buf[20];
    char send_buf[MAX_DATA];
    char send_path[1024];
    char send_over[9]="send over";
    struct sockaddr_in addr_serv;
    struct sockaddr_in addr_client;
    FILE *fd=NULL;
    
    sock_fd=socket(AF_INET,SOCK_DGRAM,0);
    if(sock_fd<0)
    {
        perror("socket error\n");
        exit(1);
    }else
    {
        printf("socket success\n");
    }
    
    
    memset(&addr_serv,0,sizeof(struct sockaddr_in));
    addr_serv.sin_family=AF_INET;
    addr_serv.sin_port=htons(SERV_PORT);
    addr_serv.sin_addr.s_addr=htonl(INADDR_ANY);//任意本地址
    
    client_len=sizeof(struct sockaddr_in);
    
    if(bind(sock_fd,(struct sockaddr*)&addr_serv,sizeof(struct sockaddr_in))<0)
    {
        perror("bind error\n");
        exit(1);
    }else
    {
        printf("bind success\n");
    }
    
    
    //设置超时时间
    struct timeval tv_out;
    tv_out.tv_sec=3;
    tv_out.tv_usec=0;
    setsockopt(sock_fd,SOL_SOCKET,SO_RCVTIMEO,&tv_out,sizeof(tv_out));
    


    bool recv_ask_flag=true;
    bool send_over_flag=false;
    bool send_again_flag=false;

    while(1)
    {
        //printf("begin receive\n");
	unsigned long saposition;

	memset(recv_buf,0,sizeof(recv_buf));
        recv_num=recvfrom(sock_fd,recv_buf,sizeof(recv_buf),0,(struct sockaddr*)&addr_client,&client_len);
        
        //printf("recv_num: %d, recv_buf: %s\n",recv_num,recv_buf);
        if(recv_num<0)
        {
          perror("receive error");
          continue;
        }else if(recv_num==12)
        {
          recv_ask_flag=true;
        }else if(recv_num==18)
	{
	  recv_ask_flag=true;
	  send_again_flag=true;
          if(fd==NULL)//文件最后一个包出错需要重发的情况
	    {
	      fd=fopen(send_path,"rb");
	      fseek(fd,saposition,SEEK_SET);
	    }
	}
        else 
        {
           if(fd!=NULL)
             fclose(fd);
           printf("receive request success : %s\n",recv_buf);
           sprintf(send_path,"/opt/imagedata/egtest01_bmp/%s",recv_buf);
           fd=fopen(send_path,"rb");
           if(fd==NULL)
    	   {
    	      printf("fail to open %s for sending\n",send_path);
    	      exit(1);
    	   }
    	   recv_ask_flag=true;
    	   send_over_flag=false; 
        }
        
        
        //printf("begin send\n");
        long int position=0;
        while(recv_ask_flag&&fd!=NULL)
        {   
            position=ftell(fd);

    	    if(fread(send_buf,1,MAX_DATA,fd)==0)
    	    {
    	      //perror("read file");
    	      recv_ask_flag=false;
	      send_again_flag=false;
    	      send_over_flag=true;
    	      break;
    	    }
    	    

            //printf("position is in %ld\n",position);

            long int send_size=(position+MAX_DATA)>FILE_LENGTH?(FILE_LENGTH-position):MAX_DATA;
    	    send_num=sendto(sock_fd,send_buf,send_size,0,(struct sockaddr*)&addr_client,client_len);
    	    //printf("send_num: %d\n",send_num);
    	    
    	    
	    if(send_num<0||send_again_flag==true)
    	    {
    	      //perror("send error"); 
    	      fseek(fd,saposition,SEEK_SET);
 	      send_again_flag=false;
    	      continue;
            }

            saposition=position;

            recv_ask_flag=false;
	    send_again_flag=false;

        }
        
        if(send_over_flag&&position==921654&&fd!=NULL)
        {
           send_num=sendto(sock_fd,send_over,9,0,(struct sockaddr*)&addr_client,client_len);
	   
           if(fd!=NULL)
           {
             fclose(fd);
             fd=NULL;
           }
        }
        	
    }
    
    close(sock_fd);
    return 0;
    
}

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值