Unix TCP-сокет send () неправильно загружает любые другие файлы, кроме файлов HTML? - PullRequest
0 голосов
/ 06 декабря 2018

Я пытаюсь создать простой HTTP-прокси, который получает HTTP-запрос GET от клиента (используя wget в Unix).Первоначально проблема заключалась в том, что я не понимал, что send () или read () / recv () не обязательно передают все данные в сокет после 1 вызова.Чтобы исправить это, я зациклил вызов read () и добавил возвращаемые значения read () вместе, пока он не вернул 0 (то есть больше нет данных для чтения).

При этом я получаю размер файла для отправки клиенту с помощью вызова send (), но пока он работает только с HTML-файлами.Я не зацикливаю вызов send (), потому что возвращаемое значение вызова всегда равно аргументу длины, переданному в;это означает, что он отправляет все данные из моего буфера обратно клиенту.

Клиент (через wget) утверждает, что загрузил 100% файла, но когда я скачиваю файл через wget без использования моего http-прокси и запускаю команду diff для полученного файла, он всегда говорит, что двоичные файлыотличаются (пробовал pdfs, pngs, jpegs и т. д.), если это не 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 голосов
/ 06 декабря 2018

Хорошо, я вижу проблему, я храню 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;
  }
...