Java網(wǎng)絡(luò)編程中的TCP/UDP詳解
Java網(wǎng)絡(luò)編程
網(wǎng)絡(luò)編程是指編寫(xiě)運(yùn)行在多個(gè)設(shè)備(計(jì)算機(jī))的程序,這些設(shè)備都通過(guò)網(wǎng)絡(luò)連接起來(lái)。
java.net 包中 J2SE 的 API 包含有類(lèi)和接口,它們提供低層次的通信細(xì)節(jié)。你可以直接使用這些類(lèi)和接口,來(lái)專(zhuān)注于解決問(wèn)題,而不用關(guān)注通信細(xì)節(jié)。
java.net 包中提供了兩種常見(jiàn)的網(wǎng)絡(luò)協(xié)議的支持:
TCP:TCP(英語(yǔ):Transmission Control Protocol,傳輸控制協(xié)議) 是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議,TCP 層是位于 IP 層之上,應(yīng)用層之下的中間層。TCP 保障了兩個(gè)應(yīng)用程序之間的可靠通信。通常用于互聯(lián)網(wǎng)協(xié)議,被稱(chēng) TCP / IP。
UDP:UDP (英語(yǔ):User Datagram Protocol,用戶數(shù)據(jù)報(bào)協(xié)議),位于 OSI 模型的傳輸層。一個(gè)無(wú)連接的協(xié)議。提供了應(yīng)用程序之間要發(fā)送數(shù)據(jù)的數(shù)據(jù)報(bào)。由于UDP缺乏可靠性且屬于無(wú)連接協(xié)議,所以應(yīng)用程序通常必須容許一些丟失、錯(cuò)誤或重復(fù)的數(shù)據(jù)包。
網(wǎng)絡(luò)分層
(1)物理層 物理層處于OSI的最底層,是整個(gè)開(kāi)放系統(tǒng)的基礎(chǔ)。物理層涉及通信信道上傳輸?shù)脑急忍亓鳎╞its),它的功能主要是為數(shù)據(jù)端設(shè)備提供傳送數(shù)據(jù)的通路以及傳輸數(shù)據(jù)。機(jī)房,硬件空調(diào)什么的。
(2)數(shù)據(jù)鏈路層 數(shù)據(jù)鏈路層的主要任務(wù)是實(shí)現(xiàn)計(jì)算機(jī)網(wǎng)絡(luò)中相鄰節(jié)點(diǎn)之間的可靠傳輸,把原始的、有差錯(cuò)的物理傳輸線加上數(shù)據(jù)鏈路協(xié)議以后,構(gòu)成邏輯上可靠的數(shù)據(jù)鏈路。需要完成的功能有鏈路管理、成幀、差錯(cuò)控制以及流量控制等。其中成幀是對(duì)物理層的原始比特流進(jìn)行界定,數(shù)據(jù)鏈路層也能夠?qū)膩G失進(jìn)行處理。交換機(jī) 雙絞線。
(3)網(wǎng)絡(luò)層 網(wǎng)絡(luò)層涉及源主機(jī)節(jié)點(diǎn)到目的主機(jī)節(jié)點(diǎn)之間可靠的網(wǎng)絡(luò)傳輸,它需要完成的功能主要包括路由選擇、網(wǎng)絡(luò)尋址、流量控制、擁塞控制、網(wǎng)絡(luò)互連等。IP,路由器。
(4)傳輸層 傳輸層起著承上啟下的作用,涉及源端節(jié)點(diǎn)到目的端節(jié)點(diǎn)之間可靠的信息傳輸。傳輸層需要解決跨越網(wǎng)絡(luò)連接的建立和釋放,對(duì)底層不可靠的網(wǎng)絡(luò),建立連接時(shí)需要三次握手,釋放連接時(shí)需要四次揮手。
(5)應(yīng)用層 應(yīng)用層為OSI的最高層,是直接為應(yīng)用進(jìn)程提供服務(wù)的。其作用是在實(shí)現(xiàn)多個(gè)系統(tǒng)應(yīng)用進(jìn)程相互通信的同時(shí),完成一系列業(yè)務(wù)處理所需的服務(wù)。約定數(shù)據(jù)內(nèi)容和格式。
TCP/UDP
TCP(傳輸控制協(xié)議) TCP是面向連接的協(xié)議,因此每個(gè)TCP連接都有3個(gè)階段:連接建立、數(shù)據(jù)傳送和連接釋放。
連接建立經(jīng)歷三個(gè)步驟,通常稱(chēng)為“三次握手”。
握手過(guò)程中傳送的包里不包含數(shù)據(jù),三次握手完畢后,客戶端與服務(wù)器才正式開(kāi)始傳送數(shù)據(jù)。
(TCPServer)
package com.lanou.test; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; public class TCPServer { public static void main(String[] args) { //JAVA的TCP編程中,BIO模型使用一個(gè)工具實(shí)現(xiàn)TCP編程,這個(gè)工具叫做Socket,服務(wù)端叫ServerSocket, try { ServerSocket ss = new ServerSocket(65535);//這個(gè)端口號(hào) 寫(xiě)死 固定的 //這個(gè)是客戶端發(fā)送上來(lái)的鏈接,服務(wù)器使用這個(gè)鏈接做數(shù)據(jù)處理 Socket s = ss.accept(); //分別是兩個(gè)指針對(duì)當(dāng)前聯(lián)機(jī)的輸入輸出流 OutputStream os = s.getOutputStream(); InputStream is = s.getInputStream(); //改變輸入輸出流的狀態(tài)(套一個(gè)其它流) PrintWriter pw = new PrintWriter(os); Scanner scanner = new Scanner(System.in); BufferedReader br = new BufferedReader(new InputStreamReader(is)); while(true) { String str= scanner.nextLine(); //nextline 阻塞式代碼 pw.println(str); pw.flush(); if(str.equals("")) { break; } str = br.readLine(); System.out.println("我是服務(wù)器,我收到客戶端消息" + str); if(str.equals("")) { break; } } } catch (IOException e) { e.printStackTrace(); } } }
(TCPClient)
package com.lanou.test; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.Socket; import java.net.UnknownHostException; import java.util.Scanner; public class TCPClient { public static void main(String[] args) { //客戶端,直接使用Sockert工具 try { Socket s = new Socket("127.0.0.1", 65535); // host 鏈接到那個(gè)主機(jī)上 String的參數(shù) port端口 InputStream is = s.getInputStream(); OutputStream os = s.getOutputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); PrintWriter pw = new PrintWriter(os); Scanner scanner = new Scanner(System.in); String str; while(!(str = br.readLine()).equals("")) { System.out.println("客戶端收到"+str); str = scanner.nextLine(); pw.println(str); pw.flush(); if(str.equals("")) { break; } } } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
(UDPServer)
package com.lanou.udp; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; public class UDP { public static void main(String[] args) { //UDP是面向報(bào)文的,所以數(shù)據(jù)傳輸過(guò)程中,是不需要建立鏈接的,只要有對(duì)應(yīng)的報(bào)文,就可以指揮網(wǎng)卡去發(fā)送這個(gè)數(shù)據(jù)包 //但是對(duì)于服務(wù)器來(lái)說(shuō),UDP雖然沒(méi)有建立鏈接,卻需要在對(duì)應(yīng)的端口上進(jìn)行監(jiān)聽(tīng),否則是有問(wèn)題的 //DatagramSocket,這個(gè)類(lèi)型是JAVA對(duì)于UDP實(shí)現(xiàn)的一個(gè)網(wǎng)絡(luò)套接字,當(dāng)我們需要使用UDP傳輸內(nèi)容的時(shí)候,只需要?jiǎng)?chuàng)建一個(gè) //DatagramSocket,對(duì)象就可以了,不用指定這個(gè)對(duì)象是否是服務(wù)(區(qū)別TCP的ServerSocket) try { DatagramSocket socket = new DatagramSocket(10086); byte[] b = new byte[1024]; DatagramPacket p =new DatagramPacket(b, b.length); while(true) { socket.receive(p); b = p.getData();//拿出數(shù)據(jù) 拆開(kāi)包裹 System.out.println(new String(b)); System.out.println(p.getAddress() + "說(shuō) : " + new String(b)); p.setData("你開(kāi)心就好".getBytes()); socket.send(p); } } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
(UDPClient)
package com.lanou.udp; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.SocketException; public class UDPClient { public static void main(String[] args) { try { DatagramSocket socket = new DatagramSocket(); String str = "我是客戶端 "; DatagramPacket p = new DatagramPacket(str.getBytes(), str.getBytes().length); p.setSocketAddress(new InetSocketAddress("127.0.0.1", 10086)); socket.send(p); socket.receive(p); System.out.println(new String(p.getData())); } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
到此這篇關(guān)于Java網(wǎng)絡(luò)編程中的TCP/UDP詳解的文章就介紹到這了,更多相關(guān)TCP/UDP詳解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java創(chuàng)建可執(zhí)行的Jar文件的方法實(shí)踐
創(chuàng)建的可執(zhí)行Jar文件實(shí)際就是在原始Jar的清單文件中添加了Main-Class的配置,本文主要介紹了Java創(chuàng)建可執(zhí)行的Jar文件的方法實(shí)踐,感興趣的可以了解一下2023-12-12IDEA一致卡在build時(shí)間過(guò)長(zhǎng)問(wèn)題解決
有很多小伙伴在起項(xiàng)目的時(shí)候巨慢,特別影響開(kāi)發(fā)效率,本文主要介紹了IDEA一致卡在build時(shí)間過(guò)長(zhǎng)問(wèn)題解決,具有一定的參考價(jià)值,感興趣的可以了解一下2024-06-06SpringDataJpa:JpaRepository增刪改查操作
這篇文章主要介紹了SpringDataJpa:JpaRepository增刪改查操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08Java實(shí)現(xiàn)二叉樹(shù)的建立、計(jì)算高度與遞歸輸出操作示例
這篇文章主要介紹了Java實(shí)現(xiàn)二叉樹(shù)的建立、計(jì)算高度與遞歸輸出操作,結(jié)合實(shí)例形式分析了Java二叉樹(shù)的創(chuàng)建、遍歷、計(jì)算等相關(guān)算法實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-03-03如何利用Java使用AOP實(shí)現(xiàn)數(shù)據(jù)字典轉(zhuǎn)換
這篇文章主要介紹了如何利用Java使用AOP實(shí)現(xiàn)數(shù)據(jù)字典轉(zhuǎn)換,AOP也是我們常說(shuō)的面向切面編程,AOP在我們開(kāi)發(fā)過(guò)程中應(yīng)用也比較多,在這里我們就基于AOP來(lái)實(shí)現(xiàn)一個(gè)數(shù)據(jù)字典轉(zhuǎn)換的案例2022-06-06java Socket編程實(shí)現(xiàn)I/O多路復(fù)用的示例
本文主要介紹了java Socket編程實(shí)現(xiàn)I/O多路復(fù)用的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-09-09Java多態(tài)成員訪問(wèn)的特點(diǎn)是什么?
在上一篇文章中介紹了方法重載和方法重寫(xiě)的區(qū)別,但是在多態(tài)情況下發(fā)現(xiàn)程序的執(zhí)行結(jié)果和我們預(yù)期的不太一樣,這篇將繼續(xù)介紹多態(tài)場(chǎng)景下,Java成員訪問(wèn)的特點(diǎn),需要的朋友可以參考下2021-06-06