Unix TCP套接字send()是否正确下载HTML文件以外的其他文件?

时间:2018-12-06 01:52:10

标签: c++ sockets unix tcp

我正在尝试创建一个简单的HTTP代理,该代理从客户端(在Unix上使用wget)接收来自客户端的HTTP GET请求。我最初遇到的问题是,我没有意识到send()或read()/ recv()不一定会在1次调用后在套接字上传输所有数据。为了解决这个问题,我循环了read()调用,并将read()的返回值加在一起,直到返回0(这意味着没有更多数据可读取)。

这样做,我得到了通过send()调用发送回客户端的文件大小,但是到目前为止,它仅适用于html文件。我不会循环send()调用,因为调用的返回值始终等于传入的length参数;表示它将缓冲区中的所有数据发送回客户端。

客户端(通过wget)声称已下载了文件的100%,但是当我通过wget下载文件而不使用我的http代理并在生成的文件上运行diff命令时,总是表示二进制文件有所不同(尝试pdf,png,jpeg等),除非它是html文件。

我真的不明白为什么会这样。下面是我的recv()/ read()循环和send()部分的代码段。

   ...//Reading from website (the HTTP GET response)
    char responsebuf[BUFFER_SIZE];
    bzero(responsebuf,BUFFER_SIZE);
    int readval = recv(newsock,responsebuf,BUFFER_SIZE,MSG_PEEK);
    cout<<"Peeking at response from website via proxy =)"<<endl;
    printf("Peeked Message is....\n\n%s\n\n", responsebuf);
    string temp(responsebuf);
    int contentlen = parseResponseLength(temp);
    cout<<"Content len from peek message is "<<contentlen<<endl; //Works
    int cumlative = 0;
    string whole_response;
    char responsebuf2[BUFFER_SIZE];
    while(1){
     ssize_t readval = recv(newsock,responsebuf2,BUFFER_SIZE,0);
     string chunk(responsebuf2);
     whole_response+=chunk;
     cout<<"Read val currently is "<<readval<<endl;
     cumlative+=readval;
     cout<<"Cumulative read val is "<<cumlative<<endl;
     if(readval==0){
      break;
     }
   }



... //Sending back to client
     char finalbuf[cumlative];
     bzero(finalbuf,cumlative);
     strncpy(finalbuf,whole_response.c_str(),cumlative);
     int sent_back = send(clients.at(i), finalbuf, cumlative, 0);
     cout<<"Number of bytes sent back to client "<<sent_back<<endl;

1 个答案:

答案 0 :(得分:0)

好的,我看到了将HTTP响应存储在字符串中并尝试使用string.c_str()发送的问题。问题在于它不适用于二进制数据,因此除文本(html,txt文件)以外的任何其他文件类型均不起作用。相反,我使用.data()函数发送。并循环以防万一第一次调用时未发送所有数据

下面的新发送代码段

 //Assuming HTTP get response is in string whole_response  
  char* finalbuf = new char[fullLen];                             
  memcpy(finalbuf,whole_response.data(),fullLen);
  //length is fullLen named var
  int returned = -1;
  int bytesSent = 0;
  int bytesRemaining = fullLen;
  while(bytesSent < fullLen){
    returned = send(clients.at(i),finalbuf+bytesSent , bytesRemaining , 0);
    if(returned == -1){
        perror("Send() data back to client failed: ");
        exit(1);
    }
    bytesSent+= returned;
    bytesRemaining -= returned;
  }