Все соединения WebSocket, исходящие из локальной сети, используют один и тот же клиентский порт (вместо эфемерного) при подключении к локальному веб-серверу. Почему?

Все соединения WebSocket, исходящие из локальной сети, используют один и тот же клиентский порт (вместо эфемерного) при подключении к локальному веб-серверу. Почему?

Я настроил веб-сервер на виртуальной машине на моем домашнем компьютере. Я настроил свой маршрутизатор на переадресацию нескольких портов (80, 443 и т. д.) на мой компьютер, а затем переадресацию их через NAT на виртуальную машину (см.диаграммадля иллюстрации). Кажется, это работает просто отлично при запуске простого сервера Apache. Однако я сталкиваюсь с проблемами при попытке использовать WebSockets.

Я настроил простой 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 — это IP моей виртуальной машины, 10.0.2.2 — шлюз виртуальной машины.

Кроме того, это касается не только порта 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>

Примечание: изначально сообщение было опубликовано на Stack Overflow, но мне посоветовали разместить его здесь.

Связанный контент