在将文件从客户端传输到服务器时丢失字节,字节值也表示一些控制字符

时间:2013-09-02 06:05:31

标签: c++ file controls character transfer

我正在编写文件传输客户端/服务器应用程序 客户端在windows7上运行并在vb.net中编写 并且服务器在linux mint上运行并用c ++编写(我使用的是vmware) 我的问题是,当我尝试将文件上传到服务器(如图像)时,收到的数据丢失了许多字节,这些字节也代表控制字符(例如EOT,ETB,...),我想它们被读作tcp控制字符并被接收操作系统忽略。 我已经使用简单的文本文件(大小高达4MB)测试了应用程序,没有任何问题。 有没有办法阻止系统忽略这些字节?

这是接收文件的c ++函数:

string readSockBytes(int port,int num,int size)
{
  int dcmbuffSize = 1460;
  int n;
  stringstream temp;
  string strBuffer,Sbuffer;
  char Rbuffer[dcmbuffSize];
  struct socketVar sockets;
  sockets = setSocket(port);
  sockets = sockListen(sockets);
  cout<<"user connected\n";
  strBuffer = readsock(sockets);
  cout<<strBuffer.substr(0,strBuffer.find("$"))<<endl;
  if(num == atoi(strBuffer.substr(0,strBuffer.find("$")).c_str()))
    Sbuffer = "ready$";     
  else
  {
    Sbuffer = "exit$";      
    close(sockets.newsockfd);
    close(sockets.sockfd);
  }
  n = writesock(sockets, Sbuffer, 100);
  if (n < 0) error("ERROR writing to socket");
  while(strBuffer.length() < fileSize)
  {
    n = read(sockets.newsockfd,Rbuffer,dcmbuffSize-1);
    if (n < 0) error("ERROR reading from socket");
    temp.str(Rbuffer);
    strBuffer = strBuffer+temp.str();
  }
  strBuffer = strBuffer.substr(0,size);
  return strBuffer;
}

1 个答案:

答案 0 :(得分:1)

问题很可能是您发送了二进制数据。二进制数据可以包含零。并且零是正常的字符串终止符。

这意味着当您执行temp.str(Rbuffer)时(假设tempstd::stringstream),那么它只会从Rbuffer获取数据直到第一个零。

而不是使用例如std::stringstream使用std::string

while(strBuffer.length() < fileSize)
{
    char buffer[2048];

    ssize_t n = read(sockets.newsockfd, buffer, sizeof(buffer));
    if (n <= 0)
    {
        // An error, or connection closed
        if (n < 0)
            error("ERROR reading from socket");
        break;
    }

    // Create a string of `n` bytes, including possible string terminators
    // and add it to out current buffer
    strBuffer += std::string(buffer, n);
}

这里要记住的重要一点是,不能将收到的数据用作字符串!如果它是二进制数据,它将最确定地包含字符串终止符,因此您必须将其视为二进制数据而不是字符串(即使您可以将其存储在std::string中)。

您还需要注意,您无法打印数据,因为许多二进制值要么不可打印,要么打印为“垃圾”。

最后,如果你读写二进制文件,你需要以二进制模式打开它们,否则你会得到字节0x0d0x0a的错误(即回车和换行)