0

我正在编写一个文件传输客户端/服务器应用程序,其中客户端在 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;
}
4

1 回答 1

1

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

这意味着当您这样做时temp.str(Rbuffer)(假设temp是 a ),它只会从第一个零开始std::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);
}

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

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

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

于 2013-09-02T06:56:00.757 回答