C套接字文件传输损坏的数据

时间:2016-04-11 02:43:23

标签: c++ c sockets tcp

根据this solution通过TCP发送图像。由于代码与其他方式相比非常优雅,并且图像和文件都是数据,我相信我们可以使用几乎相同的代码发送文件。

因此,如果我想将文件从客户端发送到服务器。

客户端

  1. 获取文件大小
  2. 发送文件大小 //以上步骤将始终有效,因此我只会在此处显示代码
  3. 将文件内容读入缓冲区

    int bytes = 0;
    for (uint i = 0;i<size;i+=bytes)
    {
        if ((bytes = send(sock,buf+i,size-i,0))<0)
        {
            fprintf(stderr,"Can not send file\n");
            close(fd);
            return false;
        }
        fprintf(stderr,"bytes write = %d\n",bytes);
    }
    
  4. 发送缓冲区

    char buf[size];
    int bytes=0;
    for (uint i = 0;i<size;i+=bytes)
    {
        if ((bytes = recv(sock,buf+i,size-i,0))<0)
        {
            fprintf(stderr,"Can not receive file\n");
            return false;
        }
        fprintf(stderr,"bytes read = %d\n",bytes);
    }
    
  5. 服务器

    1. recv文件大小
    2. 将东西收集到缓冲区中,其大小来自步骤1

      fwrite(buf,sizeof(char),size,fs);
      
    3. 将缓冲区写入文件

      {{1}}
    4. 此代码将编译并运行。

      当我从客户端向服务器发送cpp二进制文件(24k)时,由于客户端和服务器都在同一台机器(OS X)上,因此将接收该二进制文件并可以执行。

      但是如果服务器将文件转发回客户端,并且客户端多次将此文件转发回服务器,则该二进制文件将被破坏。但是发送的字节数和接收的字节数是相同的,文件大小仍然是24k。

      我想知道这里出了什么问题。

      这是操作系统错误吗?

      谢谢,

2 个答案:

答案 0 :(得分:2)

send()recv()都不保证实际发送或接收所请求的字节数。在这种情况下,返回值仍然是正数,但小于系统调用中请求的字节数。

send()recv()的手册页文档中详细记录了这一点。请重新阅读操作系统的文档以获取这些系统调用。

应用程序有责任再次尝试,发送或接收剩余的字节。

此代码假定发送的字节数是它请求发送的字节数。它看起来似乎正确处理recv()的返回状态,但不是send()。在发送的字节数较少之后,此代码仍假定发送或接收了整个内容,fwrite()系统调用将最终写入垃圾而不是文件的后半部分。

答案 1 :(得分:-1)

如果客户端和服务器都在同一个文件夹中,那么在这种情况下就像复制和粘贴文件一样。

因此,当客户端发送文件时,它将

  1. 打开文件
  2. 获取文件名/大小+发送名称/大小+发送数据
  3. 关闭文件
  4. 在服务器端,

    1. 获取文件名/大小
    2. 再次打开同一个文件
    3. 获取文件内容
    4. 关闭文件
    5. 因此,通过引起竞争条件,第2步会出现问题。