JAVA——TCP连接中Socket的正确关闭方式
基本概念
TCP協(xié)議:Transmission Control Protocol 傳輸控制協(xié)議TCP是一種面向連接(連接導(dǎo)向)的、可靠的、基于字節(jié)流的運輸層(Transport layer)通信協(xié)議,由IETF的RFC 793說明(specified)。
Socket:網(wǎng)絡(luò)上的兩個程序通過一個雙向的通信連接實現(xiàn)數(shù)據(jù)的交換,這個連接的一端稱為一個socket。
建立網(wǎng)絡(luò)通信連接至少要一對端口號(socket)。socket本質(zhì)是編程接口(API),對TCP/IP的封裝,TCP/IP也要提供可供程序員做網(wǎng)絡(luò)開發(fā)所用的接口,這就是Socket編程接口;HTTP是轎車,提供了封裝或者顯示數(shù)據(jù)的具體形式;Socket是發(fā)動機,提供了網(wǎng)絡(luò)通信的能力。
需求分析
?* 1,客戶端
?* ? ? ?創(chuàng)建Socket連接服務(wù)器(指定IP地址,端口號)通過IP地址找到對應(yīng)的服務(wù)器
?* ? ? ?調(diào)用Socket的getInputStream()和getOutputStream()方法獲取和服務(wù)器端相連的IO流
?* ? ? ?輸入流可以讀取服務(wù)器端輸出流寫出的數(shù)據(jù)
?* ? ? ?輸出流可以寫出數(shù)據(jù)到服務(wù)端的輸入流
?*?
?* 2,服務(wù)端
?* ? ? ?創(chuàng)建ServerSocket(需要指定端口號)
?* ? ? ?調(diào)用ServerSocket的accept()方法接受一個客戶端請求,得到一個Socket
?* ? ? ?調(diào)用Socket的getInputStream()和getOutputStream()方法獲取和客戶端相連的IO流
?* ? ? ?輸入流可以讀取客戶端輸出流寫出的數(shù)據(jù)
?* ? ? ?輸出流可以寫出數(shù)據(jù)到客戶端的輸入流?
問題分析
在使用socket時,需要約定好雙方讀寫完成的條件,然后關(guān)閉輸入輸出流:
socket.shutdownInput();
socket.shutdownOutput();
即當(dāng)一方寫入完成后,調(diào)用shutdownOutput關(guān)閉輸出流,這時候?qū)Ψ降膔ead方法就會返回-1,這時候?qū)Ψ骄椭滥銓懲炅?#xff0c;對方可以關(guān)閉輸入流,然后等待對方寫入完成調(diào)用shutdownOutput后己方再調(diào)用shutdownInput,雙方就正常關(guān)閉了輸入輸出流,這時候socket就不會出現(xiàn)異常了。
源代碼
Server端
public class OioServer {public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(8080);while (true) {Socket socket = serverSocket.accept();System.out.println("socket = " + socket);new Thread(() -> {try {InputStream in = socket.getInputStream();OutputStream out = socket.getOutputStream();out.write("hello! I get your message that is follow".getBytes(Charset.forName("UTF-8")));byte[] buf = new byte[1024];int len;while ((len = in.read(buf)) != -1) {System.out.print(new String(buf, 0, len, Charset.forName("UTF-8")));out.write(buf, 0, len);}out.write("\n end \n".getBytes(Charset.forName("UTF-8")));out.flush();socket.shutdownInput();socket.shutdownOutput();} catch (IOException e) {e.printStackTrace();}finally {try {socket.close();} catch (IOException e) {e.printStackTrace();}}}).start();}} }Client端
public class OioClient {public static void main(String[] args) throws IOException {Socket socket = new Socket("127.0.0.1", 8080);InputStream in = socket.getInputStream();new Thread(() -> {BufferedInputStream bufferIn = new BufferedInputStream(in);byte[] buf = new byte[1024];try {int len;while ((len = bufferIn.read(buf)) != -1) {System.out.print(new String(buf, 0, len, Charset.forName("UTF-8")));}}catch (Exception e) {e.printStackTrace();}try {socket.shutdownInput();socket.close();} catch (IOException e) {e.printStackTrace();}}).start();OutputStream out = socket.getOutputStream();int cout = 10;while (cout-- > 0) {out.write(("this time is " + System.currentTimeMillis() + "\n").getBytes("UTF-8"));}socket.shutdownOutput();} }常見異常
java.net.SocketException:socket is closed
錯誤提示的出現(xiàn)場景:
自己主動關(guān)閉了socket,但是之后還從里面讀寫數(shù)據(jù)
Software caused connection abort: socket write error
錯誤提示的出現(xiàn)場景:
對方已經(jīng)關(guān)閉socket,依舊向?qū)Ψ綄憯?shù)據(jù)
connection reset (by peer)
錯誤提示出現(xiàn)的場景:
一端socket被關(guān)閉,另一端仍然發(fā)送數(shù)據(jù),發(fā)送的第一個數(shù)據(jù)包 connection reset by peer
一端socket退出,退出時為關(guān)閉連接,另一端讀數(shù)據(jù) connection reset
參考文章
https://stackoverflow.com/questions/14010194/detecting-socket-disconnection
https://blog.csdn.net/qq_36666651/article/details/84191732
https://blog.csdn.net/qq_41264055/article/details/81353907
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的JAVA——TCP连接中Socket的正确关闭方式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: EXE4J(Windows Launch
- 下一篇: 赫夫曼编码-译码器(Huffman Co