【问题标题】:Some content of the binary file missing after receiving from client从客户端接收后二进制文件的某些内容丢失
【发布时间】:2017-05-15 03:33:01
【问题描述】:

[在此处输入图片描述][1]我已经搜索了解决方案,但没有一个对我有用,有人可以帮助我了解我可能做错了什么或我误解且未正确处理的事情代码。

例如,应该接收的文件大小是 3656713,而服务器上实际接收到的大小是 3656464。

在我的代码中,BUFFER_SIZE 是一个宏,它设置为 4096,我认为这并不重要,因为我尝试过使用不同的数字,例如 256、1024 等,

我已经附上了客户端和服务器代码。

这是正在发送媒体文件的客户端:

    while(1){
        //char buff[BUFFER_SIZE]={0};
        memset(buff, 0, BUFFER_SIZE);
        while(!feof(fp)){
            int nread = fread(buff, 1, BUFFER_SIZE, fp);
            __android_log_print(ANDROID_LOG_INFO, "Native", "%d nread %d\n", ++i, nread);
            if(nread == 0){
                __android_log_print(ANDROID_LOG_INFO, "Native", "Something went wrong while reading the file");
                break;
            }
            if(nread > 0){
                int totalWritten = 0;
                do {
                    int actualWritten;
                    actualWritten = write (sockfd, buff + totalWritten, nread - totalWritten);
                    //actualWritten = send (sockfd, buff + totalWritten, nread - totalWritten, 0);
                    if( actualWritten == - 1 ) {
                        __android_log_print(ANDROID_LOG_INFO, "Native", "Unable to write to socket \n");
                        finalStatus = false;
                        break;
                    }
                    totalWritten += actualWritten;
                } while( totalWritten < nread );
            }
            memset(buff, 0, BUFFER_SIZE);
            //usleep(2);
        }
        if(feof(fp)){
            __android_log_print(ANDROID_LOG_INFO, "Native", "End of the file reached");
            EOFReached = true;
            fclose(fp);
        }
        if(ferror(fp)){
            fclose(fp);
            __android_log_print(ANDROID_LOG_INFO, "Native", "Something went wrong while reading the file content");
        }
        break;
    }

这是正在接收媒体文件的服务器:

 buffer = (char *)malloc(BUFFER_SIZE);
 while((bytesReceived = read(sockfd, buffer, BUFFER_SIZE)) > 0){
     receivedBytes = receivedBytes + bytesReceived;
     printf("%d : Actual size : %d Received size : %d\n", ++i, actualSizeOfTheFile, receivedBytes);
     if(strncmp(buffer, "MYNEWSTRANSFERCOMPLETE", 22) == 0){
         fclose(fp);
         printf("Closed the file as server received the command : %s\n", buffer);
         break;
     }else{
         //printf("%d Bytes recived %d and the data is %s\n", ++i, bytesReceived, buffer);
         fwrite(buffer, 1, bytesReceived, fp);
     }
     memset(buffer, '\0', BUFFER_SIZE);
 }
 printf("Final string received from client is %s\n", buffer);
 memset(buffer, '\0', BUFFER_SIZE);
 printf("Total bytes received from client is :::::%d", receivedBytes);
 if((bytesReceived = read(sockfd, buffer, BUFFER_SIZE)) > 0){
     printf("Final string received from client is %s\n", buffer);
     if((write(sockfd, "You can close the socket", 24)) > 0){
         printf("Acknowledging the client to confirming for closing the connection\n");
     }else{
         printf("Unable to acknowledge the client on close confirmation of the connection\n");
     }
 }else{
     printf("Socket might have been closed by the client\n\n");
 }

我的问题是我正在尝试使用“C”通过套接字将媒体文件从 Android 客户端传输到 Linux 服务器。早些时候,当我开始简单的文件写入和读取接收和播放的媒体文件时,没有任何问题。

但突然之间,我发现在 Linux 服务器上最终接收到的文件中丢失了一些数据。

由于我无法在此处添加粘贴日志语句的屏幕截图`

客户端日志

05-15 18:59:08.072 30084-30084/com.example.user.resumablesample I/Native: 889 nread 4096 05-15 18:59:08.072 30084-30084/com.example.user.resumablesample I/Native: totalWritten : 4096 out of nread 4096 05-15 18:59:08.072 30084-30084/com.example.user.resumablesample I/Native: 890 nread 4096 05-15 18:59:08.072 30084-30084/com.example.user.resumablesample I/Native: totalWritten : 4096 out of nread 4096 05-15 18:59:08.072 30084-30084/com.example.user.resumablesample I/Native: 891 nread 4096 05-15 18:59:08.072 30084-30084/com.example.user.resumablesample I/Native: totalWritten : 4096 out of nread 4096 05-15 18:59:08.072 30084-30084/com.example.user.resumablesample I/Native: 892 nread 4096 05-15 18:59:08.072 30084-30084/com.example.user.resumablesample I/Native: totalWritten : 4096 out of nread 4096 05-15 18:59:08.072 30084-30084/com.example.user.resumablesample I/Native: 893 nread 3081 05-15 18:59:08.072 30084-30084/com.example.user.resumablesample I/Native: totalWritten : 3081 out of nread 3081 05-15 18:59:08.072 30084-30084/com.example.user.resumablesample I/Native:到达文件末尾 05-15 19:04:22.387 30084-30094/com.example.user.resumablesample W/art:暂停所有线程耗时:7.375ms

服务器日志

2513:实际大小:3656713 接收大小:3644423 接收字节:1408 2514:实际大小:3656713 接收大小:3645831 接收字节:1408 2515:实际大小:3656713 接收大小:3647239 接收字节:1408 2516:实际大小:3656713 接收大小:3648647 接收字节:1408 2517:实际大小:3656713 接收大小:3650055 接收字节:1408 2518:实际大小:3656713 接收大小:3651463 接收字节:1408 2519:实际大小:3656713 接收大小:3652871 接收字节:1408 2520:实际大小:3656713 接收大小:3654279 接收字节:1408 2521:实际大小:3656713 接收大小:3655687 接收字节:1408 2522:实际大小:3656713 接收大小:3656464 接收字节:777

服务器上的文件列表 -rw-r--r-- 1 magic_ramana magic_ramana 3653632 5 月 15 日 13:29 mynews_4zUIgxb5nh1494854941443.mp4 ` 我观察到客户端日志所说的最后一个块 3081Bytes 已被传输,但我列出的最终文件中缺少相同数量的数据。最终文件大小为 3653632,但假设为 3656713,比假设在最后一个块中传输的多 3081 个字节

【问题讨论】:

  • 顺便问一下,在问这个问题之前,我尝试了以下链接,但对我没有多大帮助http://www.binarytides.com/receive-full-data-with-recv-socket-function-in -c/stackoverflow.com/questions/684733/…
  • 发送数据后socket怎么办?
  • 您不需要任何这些memset() 调用,如果您认为这样做表明代码中的其他地方存在错误。
  • @rici,在客户端发送数据后(意味着一旦 EOF 到达)关闭文件和套接字描述符。
  • @EJP: 禁用 memset() 调用,还是同样的问题

标签: c linux sockets android-ndk


【解决方案1】:
if(strncmp(buffer, "MYNEWSTRANSFERCOMPLETE", 22) == 0){

问题就在这里。您不能依赖于接收它作为缓冲区中的第一件事和唯一的事情。 TCP 是一种流协议,可以以任何它喜欢的方式将数据传递给接收应用程序,包括一次一个字节,或合并缓冲区,或介于两者之间的任何东西,只要它以正确的顺序准确地传递所有数据一次.

我还要注意,您实际上并没有在任何地方发送这个字符串。

同样

if((write(sockfd, "You can close the socket", 24)) > 0){

并且不能保证所有这些都被离散地接收。我还要注意,您实际上并没有在任何地方接收这些数据。

您要么必须在文件之前传输文件大小,要么在发送文件后关闭套接字,而不使用任何类型的应用程序协议。

【讨论】:

  • 您好 EJP,我已经按照您的建议编辑了代码,删除了所有应用程序特定的协议检查,但又遇到了同样的问题。我已经在实际传输之前发送了文件大小,然后开始传输。在服务器端检查接收到的字节是否与文件大小匹配,否则读取套接字。
  • 我已经删除了所有应用程序特定的协议检查,并简单地读取整个内容以在服务器端接收。到达客户端的 EOF 后,关闭文件和套接字.. 不走运。
【解决方案2】:

如果您没有设置SO_LINGER 套接字选项,关闭套接字将丢弃尚未发送的排队数据。我怀疑这就是这里发生的事情。

【讨论】:

  • 设置 SO_LINGER 后我看不出有什么不同,顺便感谢您提供的信息,我对此一无所知。
  • 在这种情况下,我想是时候拿出像 www.wireshark.org 这样的数据包嗅探器来看看发生了什么。
【解决方案3】:

请注意,以下代码摘录不依赖于客户端向服务器传输的某些“临时”文本来指示传输已完成。

这里是客户端代码所需的更正

bool finalStatus = true;
size_t nread;
while( 0 < (nread = fread(buff, 1, BUFFER_SIZE, fp) ) )
    __android_log_print(ANDROID_LOG_INFO, "Native", "%d nread %d\n", ++i, nread);        

    int totalWritten = 0;
    do
    {
        ssize_t actualWritten;
        actualWritten = write (sockfd, buff + totalWritten, (ssize_t)nread - totalWritten);
        //actualWritten = send (sockfd, buff + totalWritten, nread - totalWritten, 0);
        if( actualWritten == - 1 )
        {
            __android_log_print(ANDROID_LOG_INFO, "Native", "Unable to write to socket \n");
            finalStatus = false;
            break;
        }
        totalWritten += actualWritten;
    } while( totalWritten < nread && finalStatus);
}

if( !nread )
{
    if(feof(fp))
    {
        __android_log_print(ANDROID_LOG_INFO, "Native", "End of the file reached");
        EOFReached = true;;
    }

    else if(ferror(fp))
    {
        __android_log_print(ANDROID_LOG_INFO, "Native", "Something went wrong while reading the file content");
    }
}

fclose(fp);

这里是服务器代码所需的更正

buffer = malloc(BUFFER_SIZE);
if( !buffer )
{
    perror( "malloc failed" );
    close( sockfd );
    exit( EXIT_FAILURE );
}

// implied else, malloc successful

int i = 0;
ssize_t receivedBytes = 0;
ssize_t bytesReceived;
while((bytesReceived = read(sockfd, buffer, BUFFER_SIZE)) > 0)
{
    receivedBytes = receivedBytes + bytesReceived;
    printf("%d : Actual size : %ld Received size : %ld\n", ++i, actualSizeOfTheFile, receivedBytes);
}

if( !bytesReceived )
{
    printf( "EOF reached\n" );
}

else if( 0 > bytesReceived )
{
    perror( "read failed" );
}

close( sockfd );

printf("Total bytes received from client is :::::%ld", receivedBytes);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-22
    • 1970-01-01
    • 2011-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多