連接到本機網路伺服器時,源自本機網路的 WebSocket 連線都使用相同的用戶端連接埠(而不是臨時連接埠) - 為什麼?

連接到本機網路伺服器時,源自本機網路的 WebSocket 連線都使用相同的用戶端連接埠(而不是臨時連接埠) - 為什麼?

我在家庭桌面上的虛擬機器上設定了一個網頁伺服器。我讓路由器將多個連接埠(80、443 等)轉送到我的桌面,然後透過 NAT 將它們轉送到虛擬機器(請參閱圖表用於說明)。當運行一個簡單的 apache 伺服器時,這似乎運作得很好。然而,在嘗試使用 WebSocket 時我遇到了問題。

我設定了一個簡單的 WebSocket echo 伺服器(完全複製自https://www.boost.org/doc/libs/master/libs/beast/example/websocket/server/async-ssl/websocket_server_async_ssl.cpp當然除了將 SSL 憑證變更為我自己的裝置之外)以偵聽連接埠 6164,然後我也以與其他人相同的方式轉送該連接埠。我還設定了一個簡單的網頁(參考下面的程式碼),託管在我之前提到的 apache 伺服器上,以開啟到伺服器的 websocket 並發送訊息。

伺服器似乎完全按照預期工作,我可以打開一個 WebSocket 連接,並發送一條得到回顯的消息,等等。總是兩側均使用連接埠 6164,因此一次只能出現來自我的本地網路的一個連線。對於來自本地網路之外的設備的連接來說,情況並非如此,它們使用客戶端的臨時連接埠。 (看連接埠故障圖對於測試用例)。

  1. 為什麼會發生這種情況?
  2. 我是否可以使用一些工具來追蹤整個連接路徑上發生的情況? (即透過哪些IP/連接埠轉送)
  3. 因為我對網路相當陌生:到底是什麼決定了客戶端的連接埠?只是瀏覽器本身選擇一個嗎?

一些附加資訊:當我檢查 netstat 時,監聽器顯示

tcp 0 0 0.0.0.0:6164 0.0.0.0:* 監聽 26866/./serv...

當我的網路上的任何電腦(或我的手機)連接時,它會顯示

tcp 0 0 10.0.2.15:6164 10.0.2.2:6164 已建立 26866/./serv...

但是當我斷開手機與網路的連接並使用數據,或者使用不在本地網路上的電腦時,它會讀取

tcp 0 0 10.0.2.15:6164 10.0.2.2:51616 已建立 26866/./serv...

其中 51616 臨時連接埠號碼每次都會變更。 10.0.2.15是我的VM的IP,10.0.2.2是VM的閘道。

此外,這並不是端口 6164 所獨有的,我嘗試讓伺服器偵聽其他幾個端口,並ws = new WebSocket("wss://shaun.ralsum.com:6164");相應地更改程式碼中的行,得到相同的結果。

編輯:這裡是我的路由器->桌面(左)和桌面->虛擬機器(右)的連接埠轉送規則的圖像,按照 user1686 的要求。


網頁程式碼

<!DOCTYPE HTML>

<html>
  <head>
    
    <script>
      function openConnection(){
      if(window.WebSocket){
          // Open a web socket
          ws = new WebSocket("wss://shaun.ralsum.com:6164");
          ws.onopen = function(){
          ws.send("socket open");
          document.getElementById('socketStatus').innerHTML =
              "socket connected";
          };
          ws.onmessage = function(evt){
          var recievedMessage = evt.data;
          document.getElementById('serverResponse').innerHTML =
              recievedMessage;
          };
      } else{
          document.getElementById('socketStatus').innerHTML =
          "WebSockets not supported";
      }
      }

      function sendMessage(){
      // use global web socket object to send a message
      ws.send("sending another message");
      }
      
      function closeConnection(){
      // close the web socket connection
      ws.close();
      document.getElementById('socketStatus').innerHTML =
          "socket disconnected";
      }
    </script>
    
  </head>
  
  <body>
    <p id="socketStatus">socket disconnected</p>
    <button onclick="openConnection()">create socket</button>
    <button onclick="sendMessage()">send message</button>
    <button onclick="closeConnection()">close socket</button>
    <p id="serverResponse">response from server</p>
  </body>
  
</html>

注意:最初發佈到堆疊溢出,但建議改為發佈到此處。

相關內容