我在家庭桌面上的虛擬機器上設定了一個網頁伺服器。我讓路由器將多個連接埠(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,因此一次只能出現來自我的本地網路的一個連線。對於來自本地網路之外的設備的連接來說,情況並非如此,它們使用客戶端的臨時連接埠。 (看連接埠故障圖對於測試用例)。
- 為什麼會發生這種情況?
- 我是否可以使用一些工具來追蹤整個連接路徑上發生的情況? (即透過哪些IP/連接埠轉送)
- 因為我對網路相當陌生:到底是什麼決定了客戶端的連接埠?只是瀏覽器本身選擇一個嗎?
一些附加資訊:當我檢查 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>
注意:最初發佈到堆疊溢出,但建議改為發佈到此處。