”Connection reset by peer“引發的思考
閒來無事,把之前寫的一個遊戲伺服器框架(《一個java頁遊伺服器框架》),部署到阿里雲伺服器上,測試運行了下,結果看到後臺log中打印出了“Connection reset by peer”。出於好奇疑問就查了一下相關資料,網上說一般有這幾種:
①:伺服器的併發連線數超過了其承載量,伺服器會將其中一些連線Down掉;
②:客戶關掉了瀏覽器,而伺服器還在給客戶端傳送資料;
③:瀏覽器端按了Stop
但是這幾種都可以排除,剛搭建的伺服器,就我測試連線了下不可能超過負載,而且我這是tcp長連線與瀏覽器沒半點關係。後來問了一些大神才知道,一個連線如果長時間不用防火牆或者路由器就會給你斷開,於是就會列印如上異常。現實中的解決方法就是,客戶端定時向伺服器傳送心跳包。才知道心跳包原來還有這個作用,說來甚是慚愧啊。
說到了心跳包自然又想到了另一個功能。客戶端斷電等一些列強制連線斷開的情況,可以通過心跳包機制,讓伺服器端及時知道連結斷開,從而及時清除這些無法使用的連結屍體。反過來說,如果沒有心跳包,那麼客戶端強制斷開,伺服器是無法及時捕獲到連結斷開的事件的。然而在我測試下,強制關閉客戶端,伺服器端是會丟擲異常的(我的這個框架使用了mina,客戶端強制斷開後,會呼叫對應的exceptionCaught方法丟擲異常,然後又呼叫sessionClosed關閉連線)。既然伺服器會丟擲異常,自然我們不用通過心跳包,伺服器端也能及時知道客戶端連線斷開的情況。
懷著強烈的好奇心就做了如下測試,由於java網路程式設計有bio和nio以及最新的aio,對於AIO,成產環境中我還沒有接觸到又用這個的,所以暫不做測試,就針對BIO和NIO做測試
(以下程式碼比較簡單,就不做解釋了。僅僅用於測試我的疑惑,某些不合理的地方也就不必在意了)
BIO測試程式:
伺服器端測試程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class BIOServer
{
public static void main(String[]
args) throws UnsupportedEncodingException
{ byte []
datas= "hello" .getBytes( "UTF-8" );
try {
ServerSocket
ss = new ServerSocket( 810 );
while ( true ){
Socket
s = ss.accept();
OutputStream
os = s.getOutputStream();
os.write(datas);
}
}
|