Java TCP協(xié)議通信超詳細(xì)講解
什么是tcp
Tcp通信有兩個(gè)特點(diǎn)分別是面向連接,具有可靠性.
面向連接:指的是客戶端與服務(wù)端之間的連接,在通信之前會(huì)有三次握手的機(jī)制來(lái)確保連接的可靠性.
可靠性:tcp在確保他的可靠性上做了許多的功夫,這個(gè)可靠性體現(xiàn)在下面兩方面:
- tcp有狀態(tài):tcp會(huì)精確的紀(jì)錄哪些數(shù)據(jù)是發(fā)送了的,哪些是沒(méi)有被發(fā)送的,他保證數(shù)據(jù)包是按序到達(dá)的,不允許存在半點(diǎn)差錯(cuò)
- tcp是可以控制的:如果存在丟包或者網(wǎng)絡(luò)不好的時(shí)候,會(huì)根據(jù)具體情況對(duì)數(shù)據(jù)包進(jìn)行發(fā)送速度的控制或者對(duì)數(shù)據(jù)包進(jìn)行重新發(fā)送.
如下圖是實(shí)現(xiàn)服務(wù)器端與客戶端通信的思路:
服務(wù)端
服務(wù)端用到的類是ServerSocket
ServerSocker類在他的api文檔里面也說(shuō)了他是實(shí)現(xiàn)服務(wù)器的一個(gè)類
了解一個(gè)類我們還是老樣子先了解他的構(gòu)造方法,我們看一下api文檔
我們常用的構(gòu)造方法是第一個(gè)ServerSocket()
和第二個(gè)serverSocket(int port)
.接下來(lái)我們只講這兩個(gè)方法.
我們先來(lái)講講serverSocket()
這個(gè)構(gòu)造方法吧!
serverSocket()
這個(gè)構(gòu)造方法是創(chuàng)建一個(gè)沒(méi)有綁定端口的對(duì)象,一般他和如下方法配套使用
用以上的方法可以綁定一個(gè)你指定的ip地址和端口號(hào).
接下來(lái)我們?cè)僦v講第二個(gè)常用的構(gòu)造方法吧 !
ServerSocket(int port)
這個(gè)構(gòu)造函數(shù)創(chuàng)建的是一個(gè)綁定本機(jī)的一個(gè)自定義端口的一個(gè)ServerSocket
對(duì)象.
如下面的例子
ServerSocket serverSocket = new ServerSocket(6666); //綁定端口號(hào)為6666的端口
ServerSocket
常用的方法
accept()
方法是一個(gè)監(jiān)聽(tīng)器,是一個(gè)阻塞式,它要等有服務(wù)端來(lái)連接了才能進(jìn)行下一步,如果沒(méi)有客戶端來(lái)連接就會(huì)一直等待下去,直到接收到連接才往下運(yùn)行.這個(gè)方法返回的是一個(gè)Socket對(duì)象,有客戶端來(lái)連接,就會(huì)產(chǎn)生一個(gè)Socket對(duì)象.這個(gè)Socket對(duì)象就負(fù)責(zé)與服務(wù)端進(jìn)行通信
close
方法是釋放服務(wù)器所占用的資源,并且斷開全部客戶端的連接.
客戶端
Socket類
是實(shí)現(xiàn)客戶端通信
接下來(lái)我們解析socket
類
我們就看常用的socket類的構(gòu)造方法吧
第一個(gè)構(gòu)造方法
是創(chuàng)建一個(gè)連接到的一個(gè)指定的ip地址以及指定的端口號(hào)的服務(wù)器的socket對(duì)象.如果你得到的一個(gè)Ip地址是一個(gè)字符串類型我們還可以使用另一個(gè)構(gòu)造方法
這個(gè)構(gòu)造方法同樣的也是創(chuàng)建一個(gè)連接到的一個(gè)指定的ip地址以及指定的端口號(hào)的服務(wù)器的socket對(duì)象
我們來(lái)看看他的常用方法
我們這里著重講的是getOutputStream()
方法與getInputStream()
getOutputStream()
返回的是一個(gè)OutputStream字節(jié)輸出流對(duì)象,我們從這里可以知道我們可以發(fā)送數(shù)據(jù)給服務(wù)器/客戶端。
getInputStream()
返回有的是InputStream字節(jié)輸入流對(duì)象,我們可以通過(guò)這個(gè)對(duì)象接受服務(wù)器/客戶端發(fā)來(lái)的消息。
服務(wù)端與客戶端代碼實(shí)現(xiàn)實(shí)例
服務(wù)端代碼
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; /** * 服務(wù)端 * @author Administrator * */ public class Server { public static void main(String[] args) { ServerSocket server = null; Socket socket = null; try { //準(zhǔn)備服務(wù)器端用的通訊對(duì)象(套接字),指明端口號(hào)為8888 server = new ServerSocket(8888); //到指定端口去阻塞監(jiān)聽(tīng),一旦有客戶端請(qǐng)求發(fā)送過(guò)來(lái),那么立即自動(dòng)與客戶端建立連接 socket = server.accept(); System.out.println("服務(wù)器端準(zhǔn)備ok"); //我要發(fā)送到客戶端的內(nèi)容 String msg = "你好,我是服務(wù)器,這是我的第一次通訊,請(qǐng)問(wèn)你收到了嗎"; OutputStream os = socket.getOutputStream();//準(zhǔn)備輸出對(duì)象 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os)); bw.write(msg); bw.newLine(); bw.flush(); //接收客戶端發(fā)送的信息 InputStream is = socket.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); String reply = br.readLine(); System.out.println("我是服務(wù)器,接收到信息:"+reply); br.close(); is.close(); bw.close(); os.close(); socket.close(); server.close(); } catch (IOException e) { e.printStackTrace(); } } }
客戶端代碼
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.Socket; import java.net.UnknownHostException; /** * 客戶端 * @author Administrator * */ public class Client { public static void main(String[] args) { Socket socket = null; try { socket = new Socket("localhost", 8888); System.out.println("客戶端準(zhǔn)備完成"); //客戶端開始接受請(qǐng)求 InputStream is = socket.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); String msg = br.readLine(); System.out.println("我是客戶端,接收到信息:"+msg); //客戶端接收到服務(wù)器端的信息之后,需要反饋信息給服務(wù)器 //客戶端想要反饋給服務(wù)器端的信息 String reply = "我是客戶端,收到你的信息,這是我的反饋"; OutputStream os = socket.getOutputStream();//準(zhǔn)備客戶端的輸出流 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os)); bw.write(reply); bw.newLine(); bw.flush(); bw.close(); os.close(); br.close(); is.close(); socket.close(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
到此這篇關(guān)于Java TCP協(xié)議通信超詳細(xì)講解的文章就介紹到這了,更多相關(guān)Java TCP協(xié)議通信內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Java?redis中緩存穿透?緩存擊穿?雪崩三種現(xiàn)象以及解決方法
緩存穿透是指緩存和數(shù)據(jù)庫(kù)中都沒(méi)有的數(shù)據(jù),而用戶不斷發(fā)起請(qǐng)求,如發(fā)起為id為“-1”的數(shù)據(jù)或id為特別大不存在的數(shù)據(jù)。這時(shí)的用戶很可能是攻擊者,攻擊會(huì)導(dǎo)致數(shù)據(jù)庫(kù)壓力過(guò)大2022-01-01java實(shí)現(xiàn)自定義日期選擇器的方法實(shí)例
日期選擇器是我們?nèi)粘i_發(fā)中經(jīng)常需要用到的一個(gè)功能,下面這篇文章主要給大家介紹了關(guān)于利用java實(shí)現(xiàn)自定義日期選擇器的相關(guān)資料,文中給出了詳細(xì)的示例代碼,需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-10-10Java通過(guò)動(dòng)態(tài)代理實(shí)現(xiàn)一個(gè)簡(jiǎn)單的攔截器操作
這篇文章主要介紹了Java通過(guò)動(dòng)態(tài)代理實(shí)現(xiàn)一個(gè)簡(jiǎn)單的攔截器操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07詳解SpringBoot構(gòu)建的Web項(xiàng)目如何在服務(wù)端校驗(yàn)表單輸入
這篇文章主要介紹了詳解SpringBoot構(gòu)建的Web項(xiàng)目如何在服務(wù)端校驗(yàn)表單輸入,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10數(shù)據(jù)庫(kù)連接池c3p0配置_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家詳細(xì)介紹了數(shù)據(jù)庫(kù)連接池c3p0配置的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08教大家使用java實(shí)現(xiàn)頂一下踩一下功能
這篇文章主要教大家如何使用java實(shí)現(xiàn)頂一下踩一下功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02SpringBoot之Refresh流程的簡(jiǎn)單說(shuō)明
這篇文章主要介紹了SpringBoot之Refresh流程的簡(jiǎn)單說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09java利用Apache commons codec進(jìn)行MD5加密,BASE64加密解密,執(zhí)行系統(tǒng)命令
這篇文章主要介紹了java利用apache Commons包進(jìn)行MD5加密,BASE64加密解密與執(zhí)行系統(tǒng)命令希望對(duì)大家有用2017-12-12