日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java socket 自动重连_socket 如何判断远端服务器的连接状态?连接断开,需重连...

發(fā)布時(shí)間:2024/9/18 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java socket 自动重连_socket 如何判断远端服务器的连接状态?连接断开,需重连... 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

fluent-logger-java?is a Java library, to record events via Fluentd, from Java application.?https://github.com/fluent/fluent-logger-java

使用該sdk過程發(fā)現(xiàn),tcp連接斷開之后,該sdk的重連機(jī)制無效。

2018-01-26 12:36:25,620 ERROR [org.fluentd.logger.sender.RawSocketSender] -

java.net.SocketException: Software caused connection abort: socket write error

at java.net.SocketOutputStream.socketWrite0(Native Method)

at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113)

at java.net.SocketOutputStream.write(SocketOutputStream.java:159)

at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)

at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)

at org.fluentd.logger.sender.RawSocketSender.flush(RawSocketSender.java:200)

at org.fluentd.logger.sender.RawSocketSender.send(RawSocketSender.java:188)

at org.fluentd.logger.sender.RawSocketSender.emit(RawSocketSender.java:158)

at org.fluentd.logger.sender.RawSocketSender.emit(RawSocketSender.java:140)

at org.fluentd.logger.sender.RawSocketSender.emit(RawSocketSender.java:135)

at org.fluentd.logger.FluentLogger.log(FluentLogger.java:101)

at org.fluentd.logger.FluentLogger.log(FluentLogger.java:86)

at fluentdDemo.fluentdDemo.main(fluentdDemo.java:90)

查看源碼:見RawSocketSender類

private void reconnect() throws IOException {

if (socket == null) {

connect();

} else if (socket.isClosed() || (!socket.isConnected())) {

close();

connect();

}

}

判斷 Socket 遠(yuǎn)程端連接如果關(guān)閉的話,就要重建連接。Socket的類提供了一些已經(jīng)封裝好的方法, 如 ?isClosed()、isConnected()、isInputStreamShutdown()、isOutputStreamShutdown()等,

在測試時(shí)發(fā)現(xiàn),這些方法都是本地端的狀態(tài),無法判斷遠(yuǎn)端是否已經(jīng)斷開連接。

有些同學(xué)處理類似問題時(shí),通過OutputStream發(fā)送一段測試數(shù)據(jù),如果發(fā)送失敗就表示遠(yuǎn)端已經(jīng)斷開連接,類似ping,但是這樣會(huì)影響到正常的輸出數(shù)據(jù),遠(yuǎn)端無法把正常數(shù)據(jù)和測試數(shù)據(jù)分開。

其實(shí),這種方法也是可以的,只不過,不要發(fā)送測試數(shù)據(jù),直接發(fā)送需要發(fā)送的數(shù)據(jù),一旦失敗,就主動(dòng)close socket,再新建連接,再重新發(fā)送就行了。

也有些同學(xué)想到通過發(fā)送緊急數(shù)據(jù),來驗(yàn)證連接狀態(tài),見socket類(如下),如果失敗,就close socket,再新建連接。

/**

* Send one byte of urgent data on the socket. The byte to be sent is the lowest eight

* bits of the data parameter. The urgent byte is

* sent after any preceding writes to the socket OutputStream

* and before any future writes to the OutputStream.

* @param data The byte of data to send

* @exception IOException if there is an error

* sending the data.

* @since 1.4

*/

public void sendUrgentData (int data) throws IOException {

if (!getImpl().supportsUrgentData ()) {

throw new SocketException ("Urgent data not supported");

}

getImpl().sendUrgentData (data);

}

可通過如下寫法實(shí)現(xiàn):

/**

* 判斷是否斷開連接,斷開返回true,沒有返回false

* @param socket

* @return

*/

public Boolean isServerClose(Socket socket){

try{

socket.sendUrgentData(0xFF);//發(fā)送1個(gè)字節(jié)的緊急數(shù)據(jù),默認(rèn)情況下,服務(wù)器端沒有開啟緊急數(shù)據(jù)處理,不影響正常通信

return false;

}catch(Exception se){

return true;

}

}

前提:對(duì)方Socket的SO_OOBINLINE屬性沒有打開,就會(huì)自動(dòng)舍棄這個(gè)字節(jié),而SO_OOBINLINE屬性默認(rèn)情況下就是關(guān)閉的

見SocketOptions接口

/**

* When the OOBINLINE option is set, any TCP urgent data received on

* the socket will be received through the socket input stream.

* When the option is disabled (which is the default) urgent data

* is silently discarded.

*

* @see Socket#setOOBInline

* @see Socket#getOOBInline

*/

@Native public final static int SO_OOBINLINE = 0x1003;

當(dāng)然,我覺得也可以通過定時(shí)發(fā)送緊急數(shù)據(jù)來做心跳,確保tcp長連接保活,對(duì)方可以不用回應(yīng)。

測試結(jié)果:

這兩種方式再連接斷開后的第一次發(fā)送數(shù)據(jù),并沒有異常,但是server端沒收到數(shù)據(jù)。第二次發(fā)送時(shí)候,才檢測到連接異常。

有同學(xué)的說法是:Socket通過發(fā)送數(shù)據(jù)sendUrgentData()或PrintWriter 發(fā)送數(shù)據(jù)時(shí)的數(shù)據(jù)太小,被放到緩沖區(qū)沒用實(shí)時(shí)發(fā)送導(dǎo)致的。后來嘗試設(shè)置setSendBufferSize(1)發(fā)現(xiàn)能夠正常出現(xiàn)異常,這樣就能夠判斷實(shí)時(shí)網(wǎng)絡(luò)連接斷開了。(網(wǎng)上資料說sendUrgentData是實(shí)時(shí)發(fā)送數(shù)據(jù)不經(jīng)過緩沖區(qū)的,但跟我實(shí)際測試的不一樣,有待驗(yàn)證)

查看了一下源碼,緊急數(shù)據(jù)的發(fā)送時(shí)間是,在之前write到OutputStream之后,在接下來write到OutputStream之前

/**

* Send one byte of urgent data on the socket. The byte to be sent is the lowest eight

* bits of the data parameter. The urgent byte is

* sent after any preceding writes to the socket OutputStream

* and before any future writes to the OutputStream.

* @param data The byte of data to send

* @exception IOException if there is an error

* sending the data.

* @since 1.4

*/

public void sendUrgentData (int data) throws IOException {

if (!getImpl().supportsUrgentData ()) {

throw new SocketException ("Urgent data not supported");

}

getImpl().sendUrgentData (data);

}

嘗試設(shè)置setSendBufferSize(1)發(fā)現(xiàn)能夠正常出現(xiàn)異常,這樣就能夠判斷實(shí)時(shí)網(wǎng)絡(luò)連接斷開了。

fluentd的in_forward插件提供了基于udp的心跳監(jiān)聽,遺憾的是fluent-logger-java并沒有做對(duì)應(yīng)的心跳機(jī)制。

https://docs.fluentd.org/v0.12/articles/in_forward

總結(jié)

以上是生活随笔為你收集整理的java socket 自动重连_socket 如何判断远端服务器的连接状态?连接断开,需重连...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。