网工协议基础(4)TCP/UDP协议
往期回顧
?網(wǎng)工協(xié)議基礎(chǔ)(1) OSI七層模型
網(wǎng)工協(xié)議基礎(chǔ)(2) TCP/IP四層模型
網(wǎng)工協(xié)議基礎(chǔ)(3) IP地址
歡迎關(guān)注微信公眾號【廈門微思網(wǎng)絡(luò)】。www.xmws.cn專業(yè)IT認(rèn)證培訓(xùn)19周年
主要課程:思科、華為、紅帽、ORACLE、VMware、CISP、PMP等認(rèn)證培訓(xùn)及考證?
網(wǎng)絡(luò)編程有三個要素,分別是IP地址、端口號和通信協(xié)議,這次主要講TCP與UDP這兩種通信協(xié)議,以及編程的實現(xiàn)。
IP地址
網(wǎng)絡(luò)中的計算機(jī)使用IP地址來進(jìn)行唯一標(biāo)識,IP地址有IPv4和IPv6兩種類型。IPv4采用十進(jìn)制或二進(jìn)制表示形式,十進(jìn)制是一種比較常用的表示形式,如192.168.1.131,IPv6采用十六進(jìn)制表示形式,一般不常用。
如何查看IP地址相關(guān)信息:
在Windows系統(tǒng)下,打開cmd,輸入命令ipconfig,按回車即可查看。在Linux或Mac系統(tǒng)下,打開終端,使用ifconfig命令,按回車即可查看。
端口號
端口號是計算機(jī)中的應(yīng)用程序的一個整數(shù)數(shù)字標(biāo)號,用來區(qū)分不同的應(yīng)用程序。
0 ~ 1024?為被系統(tǒng)使用或保留的端口號,0 ~ 65535為有效的端口號,也就是說我們要對一些程序定義端口號的時候,要選擇1024 ~ 65535范圍內(nèi)的整數(shù)數(shù)字。
比如,以前學(xué)過的MySQL的端口號是3306,SQLServer的端口號是1433,查了一下Oracle的端口號是1521。
一定要把這些數(shù)據(jù)庫對應(yīng)的端口號,藏在深深的腦海里,以后在連接數(shù)據(jù)庫的時候,會使用到端口號。
通信協(xié)議
說的通俗一點(diǎn),通信協(xié)議就是網(wǎng)絡(luò)通信中的規(guī)則,分為TCP協(xié)議和UDP協(xié)議兩種。
第一種:TCP協(xié)議
英文名:Transmission Control Protocol 中文名:傳輸控制協(xié)議 協(xié)議說明:TCP是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議。
舉例:打電話,需要雙方都接通,才能進(jìn)行對話
特點(diǎn):效率低,數(shù)據(jù)傳輸比較安全
第二種:UDP協(xié)議
英文名:User Datagram Protocol 中文名:數(shù)據(jù)報協(xié)議 協(xié)議說明:UDP是一種面向無連接的傳輸層通信協(xié)議。
舉例:發(fā)短信,不需要雙方建立連接,But,數(shù)據(jù)報的大小應(yīng)限制在64k以內(nèi)
特點(diǎn):效率高,數(shù)據(jù)傳輸不安全,容易丟包
三要素關(guān)系圖與網(wǎng)絡(luò)模型圖
01?網(wǎng)絡(luò)編程三要素關(guān)系圖
?02?OSI參考模型與TCP/IP參考模型
?
TCP編程
TCP是基于字節(jié)流的傳輸層通信協(xié)議,所以TCP編程是基于IO流編程。
對于客戶端,我們需要使用Socket類來創(chuàng)建對象。對于服務(wù)器端,我們需要使用ServerSocket來創(chuàng)建對象,通過對象調(diào)用accept()方法來進(jìn)行監(jiān)聽是否有客戶端訪問。
客戶端與服務(wù)器端圖解:
客戶端與服務(wù)器端實現(xiàn)步驟:
前提:創(chuàng)建一個項目,在項目中創(chuàng)建兩個模塊(model),一個模塊用來放客戶端相關(guān)代碼,一個模塊用來放服務(wù)器端相關(guān)代碼。
目錄結(jié)構(gòu)如下圖:
客戶端:
1、創(chuàng)建Socket對象,并指定服務(wù)器端應(yīng)用程序的端口號和服務(wù)器端主機(jī)的IP地址。
2、使用Socket的對象調(diào)用getOutputStream()方法來獲取字節(jié)輸出流對象。
3、調(diào)用字節(jié)輸出流的write(byte[] buf)或者write(int b)向服務(wù)器發(fā)送指定數(shù)據(jù)。
4、記得關(guān)閉流。
服務(wù)器端:
1、創(chuàng)建ServerSocket對象,并指定該應(yīng)用程序的端口號,端口號必須和客戶端指定的端口號一樣。
2、使用ServerSocket對象的accept()方法來監(jiān)聽客戶端發(fā)送過來的請求,返回值為Socket對象。
3、調(diào)用Socket對象的getInputStream()方法獲取字節(jié)輸入流對象
4、調(diào)用字節(jié)輸入流對象的read(byte[] buf)或read()方法獲取數(shù)據(jù)。
5、記得關(guān)閉流。
實例:
客戶端向服務(wù)器端發(fā)送信息,并顯示在服務(wù)器端。
Client類(客戶端)
package?cn.tkrnet.client;import?java.io.IOException; import?java.io.OutputStream; import?java.net.Socket;public?class?Client?{public?static?void?main(String[]?args)?throws?IOException?{//創(chuàng)建Socket對象,指定要發(fā)送到服務(wù)器端的IP地址,以及服務(wù)器端應(yīng)用程序接收的端口號//localhost代表本機(jī)IP地址Socket?client?=?new?Socket("localhost",9000);//獲取輸出流,用于向服務(wù)器端發(fā)送數(shù)據(jù)OutputStream?os?=?client.getOutputStream();os.write("Java?is?my?friend?!".getBytes());System.out.println("信息已發(fā)送");//關(guān)閉流os.close();client.close();} }Server類(服務(wù)器端)
package?cn.tkrnet.server;import?java.io.IOException; import?java.io.InputStream; import?java.net.ServerSocket; import?java.net.Socket;public?class?Server?{public?static?void?main(String[]?args)?throws?IOException?{System.out.println("--服務(wù)器端已開啟--");//創(chuàng)建ServerSocket對象,這里的端口號必須與客戶端的端口號相同ServerSocket?server?=?new?ServerSocket(9000);//調(diào)用方法accept(),用來監(jiān)聽客戶端發(fā)來的請求Socket?socket?=?server.accept();//獲取輸入流對象InputStream?is?=?socket.getInputStream();//讀取輸入流中的數(shù)據(jù)int?b?=?0;while?((b?=is.read())?!=?-1){System.out.print((char)b);}//關(guān)閉流is.close();socket.close();server.close();} }提示:在運(yùn)行程序時,一定要先運(yùn)行服務(wù)器端的程序代碼,再運(yùn)行客戶端的程序代碼。因為客戶端要向服務(wù)器發(fā)送請求,前提是服務(wù)器端要處于開啟狀態(tài)。
Server類(服務(wù)器端)運(yùn)行結(jié)果:
--服務(wù)器端已開啟--Client類(客戶端)運(yùn)行結(jié)果:
信息已發(fā)送Client類(客戶端)運(yùn)行后,Server類(服務(wù)器端)收到信息,運(yùn)行結(jié)果:
--服務(wù)器端已開啟-- Java?is?my?friend?!2021 最新 Java 面試題出爐。
實例分析:
服務(wù)器端啟動后,服務(wù)器端的accept()方法一直處于監(jiān)聽狀態(tài),直到客戶端連接了服務(wù)器,服務(wù)器端再從流中讀取客戶端發(fā)來的數(shù)據(jù)。
恕我直言,這是一個超級無敵簡單的單向通信實例。
UDP編程
UDP使用數(shù)據(jù)報進(jìn)行數(shù)據(jù)傳輸,沒有客戶端與服務(wù)器端之分,只有發(fā)送方與接收方,兩者哪個先啟動都不會報錯,但是會出現(xiàn)數(shù)據(jù)丟包現(xiàn)象。發(fā)送的內(nèi)容有字?jǐn)?shù)限制,大小必須限制在64k以內(nèi)。
發(fā)送方與接收方實現(xiàn)步驟:
前提:創(chuàng)建一個項目,在項目中創(chuàng)建兩個模塊(model),一個模塊用來放發(fā)送方相關(guān)代碼,一個模塊用來放接收方相關(guān)代碼。
目錄結(jié)構(gòu)如下圖:
發(fā)送方:
1、創(chuàng)建DatagramSocket對象,可以指定應(yīng)用程序的端口號,也可以不指定。
2、準(zhǔn)備需要發(fā)送的數(shù)據(jù)
3、創(chuàng)建DatagramPacket對象,用來對發(fā)送的數(shù)據(jù)進(jìn)行打包,需要指定發(fā)送內(nèi)容、發(fā)送多少、發(fā)送到哪里和接收方的端口號四個參數(shù)。
4、調(diào)用DatagramSocket對象的send()方法發(fā)送數(shù)據(jù)。
5、記得關(guān)閉流。
接收方:
1、創(chuàng)建DatagramSocket對象,指定接收方的端口號,這個必須指定。
2、創(chuàng)建一個byte類型數(shù)組,用來接收發(fā)送方發(fā)送過來的數(shù)據(jù)。
3、創(chuàng)建DatagramPacket對象,準(zhǔn)備接收數(shù)據(jù)。
4、調(diào)用DatagramSocket對象的receive()方法用于接收數(shù)據(jù)。
5、使用String類的構(gòu)造方法將byte類型的數(shù)組中的數(shù)據(jù)轉(zhuǎn)化成String類型并顯示。
6、記得關(guān)閉流。
實例:
發(fā)送方發(fā)送信息,接收方接收信息,并顯示。
Sender類(發(fā)送方)
package?cn.tkrnet.Sender;import?java.io.IOException; import?java.net.*;public?class?Sender?{public?static?void?main(String[]?args)?throws?IOException?{//創(chuàng)建接受或發(fā)送的數(shù)據(jù)報套接字,并指定發(fā)送方的端口號為7770DatagramSocket?ds?=?new?DatagramSocket(7770);???//端口號也可以不指定System.out.println("---發(fā)送方---");//創(chuàng)建數(shù)據(jù)報對象,用來發(fā)送數(shù)據(jù)byte[]?b?=?"Java is my friend !".getBytes();//8800為接收方的端口號,netAddress.getByName("localhost")是獲取主機(jī)的IP地址DatagramPacket?dp?=?new?DatagramPacket(b,b.length,?InetAddress.getByName("localhost"),7788);ds.send(dp);????//發(fā)送數(shù)據(jù)報System.out.println("數(shù)據(jù)已發(fā)送");//關(guān)閉流ds.close();} }Receiver類(接收方)
package?cn.tkrnet.receiver;import?java.io.IOException; import?java.net.DatagramPacket; import?java.net.DatagramSocket;public?class?Receiver?{public?static?void?main(String[]?args)?throws?IOException?{System.out.println("---接收方---");//創(chuàng)建數(shù)據(jù)報套接字對象,指定的端口號要和發(fā)送方發(fā)送數(shù)據(jù)的端口號相同//?(不是發(fā)送方的端口號7770,是發(fā)送方發(fā)送數(shù)據(jù)的端口號7788)DatagramSocket?ds?=?new?DatagramSocket(7788);//創(chuàng)建接收數(shù)據(jù)報的對象byte[]?b?=?new?byte[1024];DatagramPacket?dp?=?new?DatagramPacket(b,b.length);//接收數(shù)據(jù)ds.receive(dp);System.out.println(new?String(b,0,dp.getLength()));//關(guān)閉流ds.close();} }提示:在運(yùn)行程序時,先運(yùn)行發(fā)送方程序,還是先運(yùn)行接收方程序都不會報錯,但是有可能會出現(xiàn)數(shù)據(jù)丟包,一般我們都先運(yùn)行接收方的程序代碼,再運(yùn)行發(fā)送方的程序代碼。
Receiver類(接收方)運(yùn)行結(jié)果:
---接收方---Sender類(發(fā)送方)運(yùn)行結(jié)果:
---發(fā)送方--- 數(shù)據(jù)已發(fā)送Sender類(發(fā)送方)運(yùn)行后,Receiver類(接收方)接收到信息,運(yùn)行結(jié)果:
---接收方--- Java is my friend !實例分析:
只有接收方先啟動運(yùn)行,才會存在端口號為7788的程序,發(fā)送方才能發(fā)送數(shù)據(jù)到指定端口號7788,接收方才能接收數(shù)據(jù)。
不瞞你說,這也是個超級無敵簡單的單向通信實例。
最后
再來一招
一張圖看懂TCP與UDP的區(qū)別
End
總結(jié)
以上是生活随笔為你收集整理的网工协议基础(4)TCP/UDP协议的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 运维基础(4)流量监控工具篇
- 下一篇: 运维基础(5)Ansible