部分udp文件传输

时间:2013-07-15 10:12:54

标签: c++ sockets udp

我有以下基本的C ++代码,用于使用linux上的套接字通过UDP传输文件。 问题是,并非所有数据包都被传送(就像收到345kb中的8个字节一样),我知道UDP不可靠,但这是否与我的代码有关,或者仅仅因为UDP的不可靠性?

客户端

sockfd=socket(AF_INET,SOCK_DGRAM,0);

bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=inet_addr("192.168.0.152");
servaddr.sin_port=htons(32000);
ifstream myfile("345kb.doc", ios::in);
int i=0;
char* memblock;
double size;
if(myfile.is_open()) {
    myfile.seekg(0,ios::end);
    size=(double)myfile.tellg();
    memblock=new char[1024];
    myfile.seekg(0,ios::beg);
    double filesize=size;
    cout<<filesize;
    int n;
    int ab=(int)filesize%1024;
    while(filesize>1024){
        myfile.read(memblock,1024);
        cout<<"\nREAD:"<<strlen(memblock)<<"\n"<<"SENT:";
        n=sendto(sockfd,memblock,strlen(memblock),0,(struct sockaddr *)&servaddr,sizeof(servaddr));
        filesize=filesize-1024;
        cout<<n<<"\n";
    }
    myfile.read(memblock,1024);
    n=sendto(sockfd,memblock,strlen(memblock),0,(struct sockaddr *)&servaddr,sizeof(servaddr));
    std::cout<<"HI"<<endl;
} else {
    printf("\nFILE NOT OPENED \n");
}

服务器端

int sockfd,n;
struct sockaddr_in servaddr,cliaddr;
socklen_t len;
char mesg[1024];

sockfd=socket(AF_INET,SOCK_DGRAM,0);

bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(32000);
bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

//for (;;)
//{
    ofstream myfile;
    myfile.open("345kbsssss.doc",ios::out|ios::app);
    if(myfile.is_open()) {
        long i=0;
        len = sizeof(cliaddr);
        while((n = recvfrom(sockfd,mesg,1024,0,(struct sockaddr *)&cliaddr,&len))>0){
            std::cout<<"HI\n";
            //n=recvfrom(sockfd,mesg,256,0,(struct sockaddr *)&cliaddr,&len);
            myfile.write(mesg,n);
        }
    }
    else printf("\nFILE NOT CREATED\n");
//}

1 个答案:

答案 0 :(得分:3)

两者都是真的:

  • 如果不实施检查,重新排序和重新传输,UDP不应用于文件传输。不是通过UDP实现所有这些,而是​​切换到TCP更好。除了极少数资源有限的嵌入式系统外。

  • 在您的代码中使用strlen来获取块长度,因为文件(最可能)是二进制文件,这会产生不正确的长度值,并且您不会传输整个文件数据。 strlen对零终止字符串进行操作,并且只计算数据中的前0个字节。

要获得更正确的结果,最简单的方法是将strlen(memblock)替换为min(1024,filesize)。这不是一个完美的解决方案,因为它不会确切地检查myfile.read读取了多少字节。