簡體   English   中英

轉發代理檢測FIN數據包

[英]Forward proxy detecting FIN packet

我已經寫了一個轉發代理。 我要在Windows和Linux上都使用它。 我確實需要根據操作系統進行更改。 但是,我仍然看到一些加薪條件。 大多數情況下,我認為它們是由於我在猜測哪個是最后一個數據包(FIN標記)時產生了誤解。 目前,我確實選擇了一組插座。 無論哪個套接字發出信號,我都會對其進行read()。 如果讀取返回0,則假定它是FIN數據包,然后關閉該套接字。 我的read()可能會給出非零值嗎? 但是該數據包確實包含FIN(我認為可能會發生)。 因此,盡管它們已關閉,但我不關閉某些套接字。 我不確定代理如何檢測哪個套接字已關閉? 或者哪個是已建立連接上的最后一個數據包。

我的代碼如下所示:

我已經從客戶那里接受了100 fds。 我將它們存儲為數組sock_array[total_size]

select(copy_of_sock_array,timeout)                                                          
for(int cnt=0;cnt<total_size;cnt++)                                                          
{                                                                                            
   if(FD_ISSET(sock_array[cnt],sock_array))                                                  
   {
            ret = recv(sock_array[cnt],buffer,len);                                          
            if(ret<=0){                                                                      
                /*This must be a FIN packet */                                               
                /* Close corresponding socket which is opened with outer world */            
                close(/*corresponding socket*/);                                                                      
            }                                                                                  
   }                                                                                          
}                                                                                                

這樣看起來還好嗎?

謝謝

您需要進行非阻塞讀取,並繼續從套接字讀取數據,直到獲得指示應該停止讀取的返回值為止。

ssize_t r = 0;
for (;;) {
    r = recv(sock, buf, bufsz, MSG_DONTWAIT);
    if (r <= 0) {
        if (r < 0 && errno == EINTR) {
            continue;
        }
        break;
    }
    /* ... handle data in buf .. */
}
if (r < 0) {
    if (errno == EAGAIN) {
        /* ... wait in select again ... */
    } else {
        /* ... handle error ... */
    }
} else {
    /* got FIN */
}

請注意,僅僅因為接收到FIN並不一定意味着應該關閉連接。 FIN僅指示不再發送更多數據,但是對等方可能仍然願意接受更多數據。 這可能發生在HTTP中,客戶端僅需要一個響應,因此它在請求后傳遞FIN。 它仍然希望收到回復。

您的代理可能有兩個套接字,例如sock1和sock2。 因此,在sock1上收到FIN意味着該指示已在隊列中排隊的任何數據已交付(鏡像也為真)之后轉發到sock2上。 您可以使用shutdown轉發FIN。

shutdown(sock2, SHUT_WR);

從sock1和sock2都收到FIN時,您可以在兩個套接字上調用close

因此,解決您的問題。

我的read()可能會給出非零值嗎? 但是該數據包確實包含FIN(我認為可能會發生)。

是的,這可能會發生。 這就是為什么您繼續閱讀直到獲得停止指示的原因。 好吧,從技術上講,您不必這樣做。 如果每個連接的公平性問題,可以將其推遲到處理其他連接為止。 但是,您需要返回到它並完成閱讀,然后再輸入選擇的等待時間。

因此,盡管它們已關閉,但我不關閉某些套接字。 我不確定代理如何檢測哪個套接字已關閉? 或者哪個是已建立連接上的最后一個數據包。

正如我所描述的,作為(透明)代理,一旦在其上轉發了FIN並且收到了FIN,便可以安全地關閉套接字。 如果您不是透明代理,則需要遵循一組不同的規則,因為在這種情況下,您確實是客戶端的服務器。 因此,只要您實現的應用程序協議允許您關閉套接字,就可以關閉套接字。

套接字具有明確定義的行為。 如果您收到數據並且此后連接已關閉,則需要兩個read()。 第一個將返回數據,第二個將返回0,以表示連接結束。

您始終必須閱讀,直到syscall返回0。

而且您不需要非阻塞讀取即可檢測到這一點!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM