利用UDP协议进行图像传输

2014年08月31日

写在前面


由于项目需要,自己实现了UPD协议下图像的快速无丢失传输,测试数据是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;  
}  

以上。


版权声明:本文为博主原创文章,转载请注明出处 本文总阅读量    次