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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

java socket 判断Socket连接失效

發(fā)布時間:2023/12/10 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java socket 判断Socket连接失效 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?

要判斷socket連接鏈路是否可用時,不能通過socket.isClosed()?和?socket.isConnected()?方法判斷,要通過心跳包 socket.sendUrgentData(0xFF) 。

當(dāng)?shù)谝淮芜B接成功后,?socket.isClosed() ==false,?socket.isConnected()==true,只有在自己端代碼中顯示調(diào)用socket.close()方法時,socket.isClosed() ==true。

而鏈路的不可用時,自己端的socket是不知道的,仍然是 socket.isClosed() ==false,?socket.isConnected()==true。

要通過心跳包 socket.sendUrgentData(0xFF)? 進(jìn)行測驗。

?

我們來看如下代碼運行后再繼續(xù):

服務(wù)端:

Java代碼??
  • package?com.service;??
  • import?java.net.*;??
  • /**?
  • ?*?@說明?從這里啟動一個服務(wù)端監(jiān)聽某個端口?
  • ?*?@author?崔素強(qiáng)?
  • ?*/??
  • public?class?DstService?{??
  • ????public?static?void?main(String[]?args)?{??
  • ????????try?{?????????????
  • ????????????//?啟動監(jiān)聽端口?8001??
  • ????????????ServerSocket?ss?=?new?ServerSocket(8001);??
  • ????????????//?沒有連接這個方法就一直堵塞??
  • ????????????Socket?s?=?ss.accept();??
  • ????????????//?將請求指定一個線程去執(zhí)行??
  • ????????????new?Thread(new?DstServiceImpl(s)).start();??
  • ????????}?catch?(Exception?e)?{??
  • ????????????e.printStackTrace();??
  • ????????}??
  • ????}??
  • }??
  • 然后我們來看執(zhí)行類,執(zhí)行類在收到連接5秒后中斷連接:

    ?

    Java代碼??
  • package?com.service;??
  • import?java.net.Socket;??
  • /**?
  • ?*?@說明?服務(wù)的具體執(zhí)行類?
  • ?*?@author?崔素強(qiáng)?
  • ?*/??
  • public?class?DstServiceImpl?implements?Runnable?{??
  • ????Socket?socket?=?null;??
  • ????public?DstServiceImpl(Socket?s)?{??
  • ????????this.socket?=?s;??
  • ????}??
  • ????public?void?run()?{??
  • ????????try?{??
  • ????????????int?index?=?1;??
  • ????????????while?(true)?{??
  • ????????????????//?5秒后中斷連接??
  • ????????????????if?(index?>?5)?{??
  • ????????????????????socket.close();??
  • ????????????????????System.out.println("服務(wù)端已經(jīng)將連接關(guān)閉!");??
  • ????????????????????break;??
  • ????????????????}??
  • ????????????????index++;??
  • ????????????????Thread.sleep(1?*?1000);??
  • ????????????}??
  • ????????}?catch?(Exception?e)?{??
  • ????????????e.printStackTrace();??
  • ????????}??
  • ????}??
  • }??
  • 我們在寫一個客戶端進(jìn)行實驗:

    Java代碼??
  • package?com.client;??
  • import?java.net.*;??
  • /**?
  • ?*?@說明?服務(wù)的客戶端,會請求連接并實時打印連接對象的一些信息,但是不會進(jìn)行流的操作?
  • ?*?@author?崔素強(qiáng)?
  • ?*/??
  • public?class?DstClient?{??
  • ????public?static?void?main(String[]?args)?{??
  • ????????try?{??
  • ????????????Socket?socket?=?new?Socket("127.0.0.1",?8001);??
  • ????????????socket.setKeepAlive(true);??
  • ????????????socket.setSoTimeout(10);??
  • ????????????while?(true)?{??
  • ????????????????System.out.println(socket.isBound());??
  • ????????????????System.out.println(socket.isClosed());??
  • ????????????????System.out.println(socket.isConnected());??
  • ????????????????System.out.println(socket.isInputShutdown());??
  • ????????????????System.out.println(socket.isOutputShutdown());??
  • ????????????????System.out.println("------------------------");??
  • ????????????????Thread.sleep(3?*?1000);??
  • ????????????}??
  • ????????}?catch?(Exception?e)?{??
  • ????????????e.printStackTrace();??
  • ????????}??
  • ????}??
  • }??
  • ??

    至于輸出結(jié)果,雖然服務(wù)端已經(jīng)中斷連接,但是客戶端一直輸出下面內(nèi)容:

    Xml代碼??
  • true??
  • false??
  • true??
  • false??
  • false??
  • ------------------------??
  • ?從連接對象的屬性信息來看,連接似乎沒有中斷。但實際雖然內(nèi)存對象可用,但是物理連接已經(jīng)失效。所以和網(wǎng)上其他抄襲來抄襲去的說法一樣,靠連接對象屬性來判斷連接的可用性是不可行的。

    大家會說那就判斷調(diào)用read方法是否報錯唄。我之前有文章已經(jīng)討論了關(guān)于調(diào)用網(wǎng)絡(luò)里面流的一些內(nèi)容,在沒有判斷這個流可用之前,我們是不會調(diào)用read方法的,當(dāng)然具體你是怎么做的我不知道我在說我的情況!

    讀取網(wǎng)絡(luò)數(shù)據(jù)流時的那個方法是這樣的:

    Java代碼??
  • public?static?byte[]?inputStreamToByte(InputStream?inStream)??
  • ????????throws?Exception?{??
  • ????int?count?=?0;??
  • ????int?haveCheck?=?0;??
  • ????//?如果在網(wǎng)絡(luò)傳輸中數(shù)據(jù)沒有完全傳遞,則方法返回0??
  • ????while?(count?==?0)?{??
  • ????????count?=?inStream.available();??
  • ????????haveCheck++;??
  • ????????if?(haveCheck?>=?50)??
  • ????????????return?null;??
  • ????}??
  • ????byte[]?b?=?new?byte[count];??
  • ????inStream.read(b);??
  • ????return?b;??
  • }??
  • ?就是說我們不會直接調(diào)用read方法,而available方法在流沒有完整和網(wǎng)絡(luò)中斷時都會返回0,不會報錯。

    就是說就算你設(shè)置超時時間設(shè)置保持連接這些東西,只要你沒有調(diào)用read的機(jī)會,你的程序就不會出問題。當(dāng)然如果程序一直不調(diào)用read方法,那這個程序可真的夠扯淡的了。

    其實只要在使用這個連接的時候判斷這個連接的可用性就行了,不要等著什么超時。

    判斷連接可用雖然網(wǎng)上一大片,其實就是那么回事,手動發(fā)送心跳包。

    Java代碼??
  • socket.sendUrgentData(0xFF);?//?發(fā)送心跳包??
  • ?如果你的連接已經(jīng)中斷,那么這個方法就會報錯。

    至于什么是心跳包,直接上理論吧。

    心跳包就是在客戶端和服務(wù)器間定時通知對方自己狀態(tài)的一個自己定義的命令字,按照一定的時間間隔發(fā)送,類似于心跳,所以叫做心跳包。 用來判斷對方(設(shè)備,進(jìn)程或其它網(wǎng)元)是否正常運行,采用定時發(fā)送簡單的通訊包,如果在指定時間段內(nèi)未收到對方響應(yīng),則判斷對方已經(jīng)離線。用于檢測TCP的異常斷開。基本原因是服務(wù)器端不能有效的判斷客戶端是否在線,也就是說,服務(wù)器無法區(qū)分客戶端是長時間在空閑,還是已經(jīng)掉線的情況。所謂的心跳包就是客戶端定時發(fā)送簡單的信息給服務(wù)器端告訴它我還在而已。代碼就是每隔幾分鐘發(fā)送一個固定信息給服務(wù)端,服務(wù)端收到后回復(fù)一個固定信息如果服務(wù)端幾分鐘內(nèi)沒有收到客戶端信息則視客戶端斷開。 比如有些通信軟件長時間不使用,要想知道它的狀態(tài)是在線還是離線就需要心跳包,定時發(fā)包收包。發(fā)包方:可以是客戶也可以是服務(wù)端,看哪邊實現(xiàn)方便合理,一般是客戶端。服務(wù)器也可以定時發(fā)心跳下去。一般來說,出于效率的考慮,是由客戶端主動向服務(wù)器端發(fā)包,而不是服務(wù)器向客戶端發(fā)。客戶端每隔一段時間發(fā)一個包,使用TCP的,用send發(fā),使用UDP的,用sendto發(fā),服務(wù)器收到后,就知道當(dāng)前客戶端還處于“活著”的狀態(tài),否則,如果隔一定時間未收到這樣的包,則服務(wù)器認(rèn)為客戶端已經(jīng)斷開,進(jìn)行相應(yīng)的客戶端斷開邏輯處理!

    當(dāng)然不能單純理解心跳包就是往對方放松數(shù)據(jù),因為心跳包是用于狀態(tài)驗證的,不是真實的數(shù)據(jù)。

    我們來看如下例子,服務(wù)端不變:

    Java代碼??
  • package?com.client;??
  • import?java.net.*;??
  • /**?
  • ?*?@說明?服務(wù)的客戶端,會請求連接并實時打印連接對象的一些信息,但是不會進(jìn)行流的操作?
  • ?*?@author?崔素強(qiáng)?
  • ?*/??
  • public?class?DstClient?{??
  • ????public?static?void?main(String[]?args)?{??
  • ????????try?{??
  • ????????????Socket?socket?=?new?Socket("127.0.0.1",?8001);??
  • ????????????socket.setKeepAlive(true);??
  • ????????????socket.setSoTimeout(10);??
  • ????????????while?(true)?{??
  • ????????????????socket.sendUrgentData(0xFF);?//?發(fā)送心跳包??
  • ????????????????System.out.println("目前是正常的!");??
  • ????????????????Thread.sleep(3?*?1000);??
  • ????????????}??
  • ????????}?catch?(Exception?e)?{??
  • ????????????e.printStackTrace();??
  • ????????}??
  • ????}??
  • }??
  • ?看到控制臺的輸出:

    Java代碼??
  • 目前是正常的!??
  • 目前是正常的!??
  • java.net.SocketException:?Invalid?argument:?send??
  • ????at?java.net.PlainSocketImpl.socketSendUrgentData(Native?Method)??
  • ????at?java.net.PlainSocketImpl.sendUrgentData(PlainSocketImpl.java:550)??
  • ????at?java.net.Socket.sendUrgentData(Socket.java:928)??
  • ????at?com.client.DstClient.main(DstClient.java:14)??
  • ?那就是說,只要你的服務(wù)端斷了,調(diào)用方法就會出錯!

    至于我說的他不會作為可見的數(shù)據(jù)你可以更改服務(wù)端代碼打印客戶端內(nèi)容,你會發(fā)現(xiàn)服務(wù)端不會將心跳包內(nèi)容展示給你!

    Java代碼??
  • InputStream?ips?=?socket.getInputStream();??
  • byte[]?bt?=?inputStreamToByte(ips);??
  • if(null?!=?bt)??
  • ????System.out.println(new?String(bt));??
  • else??
  • ????System.out.println("Bt?is?null");??
  • System.out.println("****************************");??
  • 轉(zhuǎn)載于:https://www.cnblogs.com/panchanggui/p/9664876.html

    總結(jié)

    以上是生活随笔為你收集整理的java socket 判断Socket连接失效的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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