2016-12-17 3 views
1

Так что мне нужно вернуть html-файл с сервера клиенту, файл больше, чем буфер, поэтому я делаю несколько сообщений. Вот почему у меня этот цикл, когда я ПРИЕМКак возвратить до тех пор, пока theres ничего больше, чтобы recv без eof?

while (i = recv(s, buf, TAM_BUFFER, 0)) { 
      if (i == -1) { 
       perror(argv[0]); 
       fprintf(stderr, "%s: error reading result\n", argv[0]); 
       exit(1); 
      } 
      while (i < TAM_BUFFER) { 
       j = recv(s, &buf[i], TAM_BUFFER - i, 0); 
       if (j == -1) { 
        perror(argv[0]); 
        fprintf(stderr, "%s: error reading result\n", argv[0]); 
        exit(1); 
       } 
       i += j; 
      } 
      /* Print out the file line by line. */ 
      printf("%s", buf); 
} 

посыла выглядит примерно так:

while (fgets(buf, sizeof(buf), fp)){ 
        if (send(s, buf, TAM_BUFFER, 0) != TAM_BUFFER) errout(hostname); 
       } 

Проблема является цикл никогда не заканчивается, Becase оно не Recv в ВФ и я никогда не является 0, его просто остается заблокированным. Я не могу закрыть сообщение, потому что после того, как он отобразит весь файл, клиент попросит другой файл.

Я попытался отправить SIGALRM, если цикл остается заблокированным более 5 секунд, но он не работает должным образом, потому что цикл не останавливается, и он выдает ошибку.

Также как я могу сделать, чтобы быть в состоянии recv меньше, чем TAM_BUFFER? (В send, измените TAM_BUFFER -> strlen (buf)). Я знаю, что мне нужно изменить внутреннюю петлю, но потом у нее такая же проблема , j не будет 0 никогда, поэтому я не знаю, как я могу закончить его (или, может быть, мне не нужен второй цикл в этом случае).

EDIT: я не могу отправить длину файла beucause из протокола им следующей

+0

Вам нужно отправить длину файла перед файлом и прочитать только то, что много байтов из сокета при получении файла. – EJP

+0

Я забыл добавить это, я уже искал в stackoverflow, и я нашел эту опцию, но протокол im follow dont разрешил мне использовать эту опцию. Мне нужно отправить только то, что спрашивают клиенты, и я не могу отправить длину. –

+2

Вам придется изменить протокол, за которым вы следуете, если он не поддерживает то, что вы пытаетесь сделать. – EJP

ответ

-1

Если вы не можете вставлять размер полезной нагрузки в вашем протоколе, вы должны определить EOF путем закрытия сокета или проверки тайм-аута. Вы можете использовать функцию выбора и установить для нее время ожидания, см. Здесь Using select and recv to obtain a file from a web server through a socket и https://stackoverflow.com/a/30395738/4490542

+1

Проверка таймаута не является приемлемым способом для обнаружения конца сообщения. Таймаут может произойти по любой причине. – EJP

+0

Тайм-аут очень расплывчатый. Закрытие сокета может, да. – alk

+0

@EJP внезапно, большая часть реализаций использует тайм-аут или закрывающий сокет прямо сейчас, нет никакого портативного решения без изменения протокола. –

2

TCP - протокол, используемый для транспортировки одного неструктурированного потока октетов в каждом направлении. Отключение соединения (т. Е. EOF) является единственным способом в TCP-сообщении для одноранговой сети, что в этом случае больше не будет отправлено данных. Если вам нужен другой способ, потому что вам нужно различать несколько сообщений внутри одного и того же TCP-соединения, вам необходимо использовать протокол уровня приложения, который может указывать такие границы сообщений. Обычно это делается с помощью фиксированного размера сообщения, префикса сообщения длиной или специальными маркерами границы.

-2

Так мне удалось заставить его работать, как я хотел, чтобы этот путь:

i=1; 
while (i) { 
    alarm(TIMEOUT); 
    i=recv(s, buf, TAM_BUFFER, 0); 
    if (i == -1) { 
     if (errno == EINTR){ 
      break; 
     } 
     else{ 
      perror(argv[0]); 
      fprintf(stderr, "%s: error reading result\n", argv[0]); 
      exit(1); 
     } 
    } 
} 

Это приведет к выходу из цикла с закрытием, но если его заблокировали так долго это будет сделать перерыв. EINTR означает, что операция была прервана, если другая ошибка приводит к возврату returnin -1.

+0

Не обманывайте себя. Таймаут может произойти по любой причине, как я сказал выше, не только потому, что файл закончился. Это не жизнеспособное решение. – EJP

+0

Я сам не киддин, я просто должен был сделать это так, потому что у меня не было другого варианта, если вы не можете закрыть сокет или отправить размер раньше или иметь фиксированную длину g –