8

利用UDP协议进行图像传输

 3 years ago
source link: http://lanbing510.info/2014/08/31/ImageTranslation-Using-UDP.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

利用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;  
}  

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK