2016-12-17 73 views
1

所以我需要從服務器到客戶端的recv一個HTML文件,該文件是比緩衝區更大,所以我讓幾個發送。這就是爲什麼我有這樣的循環,當我的recv如何recv直到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的EOF,我從來都不是0,它只是在那裏阻止。 我不能做接近發送的eof,因爲他recv整個文件後,客戶端會要求另一個文件。

我tryed如果循環受阻停留時間超過5秒,但它不按預期方式工作,因爲循環不會停止發送SIGALRM,它會拋出一個錯誤。我知道我需要改變內部循環,但然後生病都有同樣的問題(012) ,j永遠不會是0,所以我不知道我該如何結束它(或者我不需要第二個循環)。

編輯:我不能發送文件的lenght beucause協議IM以下

+0

您需要發送提前文件的文件的長度,且僅接收文件時讀取插座正是許多字節。 – EJP

+0

我忘了補充一點,我已經在stackoverflow中搜索,我發現該選項,但協議im下面不讓我使用該選項。我只需要發送客戶要求的內容,而且我無法發送長度。 –

+2

如果它不支持你想要做的事情,你將不得不改變你所關注的協議。 – EJP

回答

-1

如果你無法在協議中嵌入有效載荷的大小,你必須通過關閉插座或者檢查超時,以確定EOF。您可以使用選擇功能併爲其設置超時時間,請參閱此處Using select and recv to obtain a file from a web server through a sockethttps://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表示操作被中斷,以防其他錯誤導致recv returnin -1。

+0

不要欺騙自己。如上所述,超時可能會以任何原因發生,不僅僅是因爲文件已經結束。這不是一個可行的解決方案。 – EJP

+0

我不是在開玩笑,我只是這樣做,因爲我沒有任何其他的選擇,如果你不能關閉插座,或發送的大小之前,或有一個固定的長度克 –