利用UDP协议进行图像传输

由于项目需要,自己实现了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;  
}  
转载来自:
http://lanbing510.info/2014/08/31/ImageTranslation-Using-UDP.html

http://blog.csdn.net/lanbing510/article/details/38952555

  • 6
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 基于Qt平台利用UDP协议传输大图片的方法如下: 1. 双方共同约定数据传输格式:在发送端和接收端都需要确定图片的格式,比如JPEG、PNG等。这样可以确保双方在传输过程中使用相同的格式解析图片数据。 2. 发送端将大图片切分为适当大小的数据包:由于UDP协议没有拆分和重组数据包的机制,所以发送端需要将大图片切分为适当大小的数据包以适应UDP协议传输。 3. 发送端将切分后的数据包发送到接收端:利用UDP协议的广播或单播功能,发送端将切分后的数据包发送到接收端的指定地址和端口。 4. 接收端接收数据包并重新组装图片:接收端侦听指定的地址和端口,接收来自发送端的数据包。接收端需要根据数据包的顺序和大小重新组装图片。 5. 接收端显示接收到的图片:接收端在重新组装图片后,可以利用Qt平台提供的图形库显示接收到的图片。 需要注意的是,由于UDP协议是一种面向无连接并且不可靠的协议,因此在图片传输时可能会存在数据包丢失或乱序的情况。为了提高传输的可靠性,可以在应用层引入一些算法,比如给每个数据包添加序号、校验和等信息来检测和纠正错误。另外,还可以考虑引入一些窗口管理机制来控制发送和接收的速率,以适应网络环境的变化。 ### 回答2: 基于Qt平台利用UDP协议传输大图片需要进行以下步骤: 首先,我们需要将图片进行分割成小块。由于UDP协议传输数据大小的限制,一次传输整个大图片可能会导致数据丢失或者传输过程中的延迟较高。因此,我们需要将大图片分割成多个小块。 接下来,我们使用Qt提供的UDP套接字类(QUdpSocket)来实现UDP通信。我们创建一个UDP发送端和一个UDP接收端,通过网络传输图像的小块。 在发送端,我们将分割后的图像块转换为QByteArray类型,并使用QUdpSocket的writeDatagram()函数发送数据包。同时,我们可以设置目标IP地址和端口号,以便接收端能正确接收数据。 在接收端,我们创建一个QUdpSocket对象,并使用bind()函数将其绑定到指定的IP地址和端口号上。然后,我们使用QUdpSocket的readyRead()信号与对应的槽函数来接收数据包。在槽函数中,我们可以使用readDatagram()函数来读取接收到的数据,并进行相应的处理。 在接收端,我们还需要重组接收到的图像块。我们可以使用一个QByteArray来存储接收到的所有数据,并使用一个计数器(或其他方式)来确定是否已经接收到了所有图像块。一旦确定接收到了完整的图像数据,我们可以将其重新组合成完整的图像。 最后,我们可以通过显示图像窗口或保存图像文件来查看接收到的完整图像。 需要注意的是,由于UDP协议的不可靠性,传输过程中会存在丢包或乱序等情况。因此,我们需要进行适当的错误处理和容错机制,例如设置超时时间、重传机制等,以确保图像数据能够完整地传输和接收。 ### 回答3: 基于Qt平台利用UDP协议传输大图片的步骤如下: 1. 创建一个Qt应用程序,包括发送端和接收端两个部分。 2. 在发送端,使用Qt的网络模块创建一个UDP套接字,并绑定到特定的IP地址和端口号上。 3. 将要发送的大图片分割成小块,以便每次发送一个固定大小的数据包。可以使用Qt的图像处理模块来切割图片。 4. 将每个小块图片的数据打包成一个UDP数据报文,其中包括数据包的序号和总数据包数等信息。 5. 在发送端,使用UDP套接字的writeDatagram函数将数据报文发送给接收端的IP地址和端口号。 6. 在接收端,创建一个UDP套接字,并绑定到相同的IP地址和端口号。 7. 在接收端,使用UDP套接字的readyRead信号连接一个槽函数,该槽函数在接收到一个数据包时被触发。 8. 在槽函数中,通过UDP套接字的readDatagram函数读取接收到的数据包。 9. 在接收端,将接收到的数据包中的图片数据存储起来。 10. 重复步骤7到9,直到接收到所有的数据包。 11. 在接收端,使用Qt的图像处理模块将接收到的图片数据合并成完整的大图片。 需要注意的是,UDP是一种不可靠的传输协议,因此在实际应用中需要考虑一些额外的因素,如数据包的丢失和乱序等情况的处理。可以通过引入一些重传机制和序号控制等方式来增加数据传输的可靠性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值