Java TCP網(wǎng)絡(luò)通信協(xié)議詳細(xì)講解
TCP與UDP都屬于TCP/IP協(xié)議
TCP(Transmission Control Protocol,傳輸控制協(xié)議)是面向連接的協(xié)議,也就是說(shuō),在收發(fā)數(shù)據(jù)前,必須和對(duì)方建立可靠的連接。 一個(gè)TCP連接必須要經(jīng)過(guò)三次“對(duì)話”才能建立起來(lái),其中的過(guò)程非常復(fù)雜, 只簡(jiǎn)單的描述下這三次對(duì)話的簡(jiǎn)單過(guò)程:
1)主機(jī)A向主機(jī)B發(fā)出連接請(qǐng)求數(shù)據(jù)包:“我想給你發(fā)數(shù)據(jù),可以嗎?”,這是第一次對(duì)話;
2)主機(jī)B向主機(jī)A發(fā)送同意連接和要求同步 (同步就是兩臺(tái)主機(jī)一個(gè)在發(fā)送,一個(gè)在接收,協(xié)調(diào)工作)的數(shù)據(jù)包 :“可以,你什么時(shí)候發(fā)?”,這是第二次對(duì)話;
3)主機(jī)A再發(fā)出一個(gè)數(shù)據(jù)包確認(rèn)主機(jī)B的要求同步:“我現(xiàn)在就發(fā),你接著吧!”, 這是第三次對(duì)話。
三次“對(duì)話”的目的是使數(shù)據(jù)包的發(fā)送和接收同步, 經(jīng)過(guò)三次“對(duì)話”之后,主機(jī)A才向主機(jī)B正式發(fā)送數(shù)據(jù)。
TCP的三次握手過(guò)程保證了傳輸?shù)陌踩?,同時(shí)會(huì)確認(rèn)對(duì)方是否接受到信息
斷開(kāi)的時(shí)候進(jìn)行四次
UDP(User Data Protocol,用戶數(shù)據(jù)報(bào)協(xié)議)是一個(gè)非連接的協(xié)議,傳輸數(shù)據(jù)之前源端和終端不建立連接, 當(dāng)它想傳送時(shí)就簡(jiǎn)單地去抓取來(lái)自應(yīng)用程序的數(shù)據(jù),并盡可能快地把它扔到網(wǎng)絡(luò)上。 在發(fā)送端,UDP傳送數(shù)據(jù)的速度僅僅是受應(yīng)用程序生成數(shù)據(jù)的速度、 計(jì)算機(jī)的能力和傳輸帶寬的限制; 在接收端,UDP把每個(gè)消息段放在隊(duì)列中,應(yīng)用程序每次從隊(duì)列中讀一個(gè)消息段。
由于不需要像TCP那樣的握手過(guò)程,使得UDP的傳輸速度非??旖?,但他不保證傳輸?shù)陌踩?,也不確認(rèn)對(duì)方是否接收到信息
實(shí)現(xiàn)代碼:
//向指定ip發(fā)送信息 public static void main(String[] args) throws Exception{ Socket s=new Socket(InetAddress.getByName(InetAddress.getLocalHost().getHostAddress()),10000); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); //封裝輸出流對(duì)象 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); String line; while (true) { if ((line=br.readLine())!=null){ if("1024".equals(line)) { bw.write(line); bw.newLine(); break; } bw.write(line); bw.newLine(); } bw.flush(); //獲取輸出流對(duì)象 } //釋放資源 s.close(); }
//接收發(fā)送到本機(jī)的信息 ServerSocket socket=new ServerSocket(10000); Socket accept = socket.accept(); BufferedReader br = new BufferedReader(new InputStreamReader(accept.getInputStream())); String line; while ((line=br.readLine())!=null){ System.out.println(line); }
要讓倆臺(tái)進(jìn)行互通就可以實(shí)現(xiàn)了,讓他們運(yùn)行到一起可以使用線程進(jìn)行封裝。
UDP使用的是
//創(chuàng)建發(fā)送端的Socket對(duì)象(DatagramSocket) //創(chuàng)建數(shù)據(jù),并把數(shù)據(jù)打包 //DatagramPacket(byte[] buf, int length, InetAddress address, int port) //構(gòu)造一個(gè)數(shù)據(jù)包,發(fā)送長(zhǎng)度為 length的數(shù)據(jù)包到指定主機(jī)上的指定端口號(hào)。
使用UDP需要將ip地址固定成ipconfig所顯示的ip網(wǎng)關(guān)等內(nèi)容
DatagramSocket ds = new DatagramSocket(); byte[] bys = "hello,udp,我來(lái)了".getBytes(); DatagramPacket dp = new DatagramPacket(bys,bys.length, InetAddress.getByName("10.102.13.18"),10086); //調(diào)用DatagramSocket對(duì)象的方法發(fā)送數(shù)據(jù) //void send(DatagramPacket p) 從此套接字發(fā)送數(shù)據(jù)報(bào)包 ds.send(dp); System.out.println("已發(fā)送:"+new String(dp.getData(),0,dp.getLength())); //關(guān)閉發(fā)送端 //void close() 關(guān)閉此數(shù)據(jù)報(bào)套接字 ds.close();
DatagramSocket ds = new DatagramSocket(10086); while (true) { //創(chuàng)建一個(gè)數(shù)據(jù)包,用于接收數(shù)據(jù) byte[] bys = new byte[1024]; DatagramPacket dp = new DatagramPacket(bys, bys.length); //調(diào)用DatagramSocket對(duì)象的方法接收數(shù)據(jù) ds.receive(dp); System.out.println("-----"); //解析數(shù)據(jù)包,并把數(shù)據(jù)在控制臺(tái)顯示 System.out.println("數(shù)據(jù)是:" + new String(dp.getData(), 0, dp.getLength())); }
我們同樣使用DatagramSocket 方法進(jìn)行接收數(shù)據(jù)
到此這篇關(guān)于Java TCP網(wǎng)絡(luò)通信協(xié)議詳細(xì)講解的文章就介紹到這了,更多相關(guān)Java TCP內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
深入理解happens-before和as-if-serial語(yǔ)義
本文大部分整理自《Java并發(fā)編程的藝術(shù)》,溫故而知新,加深對(duì)基礎(chǔ)的理解程度。下面可以和小編來(lái)一起學(xué)習(xí)下2019-05-05Java?C++題解leetcode字符串輪轉(zhuǎn)KMP算法詳解
這篇文章主要為大家介紹了Java?C++題解leetcode字符串輪轉(zhuǎn)KMP算法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09創(chuàng)建SpringBoot工程并集成Mybatis的方法
這篇文章主要介紹了創(chuàng)建SpringBoot工程并集成Mybatis,需要的朋友可以參考下2018-06-06MyBatis-Plus 插件擴(kuò)展的實(shí)現(xiàn)
MyBatis-Plus通過(guò)插件擴(kuò)展機(jī)制增強(qiáng)功能,基于MyBatis Interceptor攔截器,包括分頁(yè)插件、邏輯刪除、SQL性能分析和樂(lè)觀鎖等,開(kāi)發(fā)者可自定義插件以適應(yīng)特定需求,有效地增強(qiáng)SQL執(zhí)行過(guò)程的控制和優(yōu)化,同時(shí)注意插件使用的性能影響和執(zhí)行順序2024-09-09Springboot如何配置yml文件與映射到j(luò)ava類(lèi)
這篇文章主要介紹了Springboot如何配置yml文件與映射到j(luò)ava類(lèi)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09SpringBoot使用JTA實(shí)現(xiàn)對(duì)多數(shù)據(jù)源的事務(wù)管理
了解事務(wù)的都知道,在我們?nèi)粘i_(kāi)發(fā)中單單靠事務(wù)管理就可以解決絕大多數(shù)問(wèn)題了,但是為啥還要提出JTA這個(gè)玩意呢,到底JTA是什么呢?他又是具體來(lái)解決啥問(wèn)題的呢?本文小編就給大家介紹一下如何在Spring Boot中使用JTA實(shí)現(xiàn)對(duì)多數(shù)據(jù)源的事務(wù)管理2023-11-11SpringBoot2.0整合Redis自定義注入bean組件配置的實(shí)戰(zhàn)教程
這篇文章主要介紹了SpringBoot2.0整合Redis自定義注入bean組件配置,我們將基于SpringBoot2.0整合搭建的微服務(wù)項(xiàng)目為奠基,開(kāi)啟中間件Redis的實(shí)戰(zhàn)之路,需要的朋友可以參考下2023-06-06Mybatis in條件傳參的三種實(shí)現(xiàn)方式(直接$,List,[])
這篇文章主要介紹了Mybatis in條件傳參的三種實(shí)現(xiàn)方式(直接$,List,[]),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12