2011-08-19 38 views
0

我正在寫一個基本的HTTP客戶端,並遇到了一個問題 - 一些HTTP服務器被強迫復位,通過使「連接復位同行「錯誤。很多HTTP服務器會優雅地關閉連接,儘管似乎沒有任何連接保持活動狀態。HTTP客戶端從一些服務器而不是其他人得到「對方將連接復位」(TCP RST)

不過,我敢肯定,這是我的客戶,因爲使用非常相似的源代碼HTTP客戶端不會出現相同的行爲:他們在同一服務器的連接或者正常關閉或維持生命。

什麼導致了這種表面上矛盾的問題呢?

相關代碼:

/* socket */ 
if ((context->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { 
    perror("Failed to create socket"); 
    exit(-1); 
} 

/* connect */ 
if (connect(context->socket, &context->tx_addr, sizeof(struct sockaddr)) != 0) { 
    perror("Couldn't connect to server"); 
    exit(-1); 
} 

/* create header */ 
snprintf(context->packet, BUFF_SIZE, 
     "GET %s HTTP/1.1\r\n" \ 
     "Host: %s\r\n\r\n", 
     conf->request, conf->host); 

/* send header */ 
if ((sendto(context->socket, context->packet, BUFF_SIZE, 0, 
      NULL, 0))) != BUFF_SIZE) { 
    perror("Failed to send"); 
    exit(-1); 
} 

/* receive response */ 
do { 
    if ((received = recvfrom(context->socket, context->packet, BUFF_SIZE, 0, NULL, 
          NULL)) < 0) { 

     /* THIS is where RST occurs with some servers */ 

     perror("Failed to receive"); 
     exit(-1) 
    } 

    if (received >= 0)  
      context->packet[received] = '\0'; 
    printf("%s", context->packet); 

} while (received > 0); 

回答

0

經過一番調查,很明顯,我的HTTP請求的格式有誤。

問題就出在這個代碼:

/* create header */ 
snprintf(context->packet, BUFF_SIZE, 
     "GET %s HTTP/1.1\r\n" \ 
     "Host: %s\r\n\r\n", 
     conf->request, conf->host); 

/* send header */ 
if ((sendto(context->socket, context->packet, BUFF_SIZE, 0, 
      NULL, 0)) != BUFF_SIZE) { 
    perror("Failed to send entire buffer"); 
    exit(-1); 
} 

注意,從緩衝區BUFF_SIZE字節發送,即使我們與snprintf創建的標題時,幾乎可以肯定不會填滿整個緩衝區。正在傳輸生成的頭文件的垃圾也正在傳輸。有些服務器忽略了錯誤的請求,其他服務器只是放棄並重置(RST)連接。

只需發送代碼更改爲這樣的事情來解決這個問題:

/* assuming context->packet is a string */ 
int len = strlen(context->packet); 
int sent = 0, total = 0; 

while (total < len) { 
    if ((sent = sendto(context->socket, context->packet + total, 
         len - total, 0, NULL, 0)) <= 0) { 
     perror("Failed to send"); 
     exit(-1); 
    } 
    total += sent; 
} 
+0

'SENDTO(...)= BUF_SIZE'是錯誤的!首先,你現在發送的比這還少。其次,TCP可能緩衝的次數少於發送給它的時間。 –

+0

如果我沒有記錯,這取決於標誌。也就是說,沒有任何標誌sendto將會阻塞,直到請求的數量像write()那樣發送。 – TimCinel

+1

不,它寫入任何空間是插座的發送緩衝區並返回可用。你可能在簡單情況下看不到這種情況,但是在較重的流量下,確實發生了短暫的寫入。 –

相關問題