網絡編程有三個要素,分別是IP地址、端口號和通訊協議,那本文主要講述的是TCP與UDP這兩種通訊協議,以及編程的實現。java
首先,咱們須要瞭解一下IP地址、端口號、通訊協議的相關知識。面試
網絡中的計算機使用IP地址來進行惟一標識,IP地址有IPv4和IPv6兩種類型。IPv4採用十進制或二進制表示形式,十進制是一種比較經常使用的表示形式,如192.168.1.131
,IPv6採用十六進制表示形式,通常不經常使用。spring
如何查看IP地址相關信息:數據庫
在Windows系統下,打開cmd,輸入命令ipconfig
,按回車便可查看。在Linux或Mac系統下,打開終端,使用ifconfig
命令,按回車便可查看。編程
端口號是計算機中的應用程序的一個整數數字標號,用來區分不一樣的應用程序。數組
0 ~ 1024
爲被系統使用或保留的端口號,0 ~ 65535
爲有效的端口號,也就是說咱們要對一些程序定義端口號的時候,要選擇1024 ~ 65535範圍內的整數數字。安全
好比,之前學過的MySQL的端口號是3306,SQLServer的端口號是1433,查了一下Oracle的端口號是1521。服務器
必定要把這些數據庫對應的端口號,藏在深深的腦海裏,之後在鏈接數據庫的時候,會使用到端口號。網絡
說的通俗一點,通訊協議就是網絡通訊中的規則,分爲TCP協議和UDP協議兩種。intellij-idea
英文名:Transmission Control Protocol 中文名:傳輸控制協議 協議說明:TCP是一種面向鏈接的、可靠的、基於字節流的傳輸層通訊協議。
舉例:打電話,須要雙方都接通,才能進行對話
特色:效率低,數據傳輸比較安全
英文名:User Datagram Protocol 中文名:數據報協議 協議說明:UDP是一種面向無鏈接的傳輸層通訊協議。
舉例:發短信,不須要雙方創建鏈接,But,數據報的大小應限制在64k之內
特色:效率高,數據傳輸不安全,容易丟包
一、網絡編程三要素關係圖
注:圖中端口號、IP地址爲演示,並不是真實
二、OSI參考模型與TCP/IP參考模型
TCP是基於字節流的傳輸層通訊協議,因此TCP編程是基於IO流編程。
對於客戶端,咱們須要使用Socket
類來建立對象。對於服務器端,咱們須要使用ServerSocket
來建立對象,經過對象調用accept()
方法來進行監聽是否有客戶端訪問。
客戶端與服務器端圖解:
客戶端與服務器端實現步驟:
前提:建立一個項目,在項目中建立兩個模塊(model),一個模塊用來放客戶端相關代碼,一個模塊用來放服務器端相關代碼。
目錄結構以下圖
客戶端:
一、建立Socket
對象,並指定服務器端應用程序的端口號和服務器端主機的IP地址。
二、使用Socket
的對象調用getOutputStream()
方法來獲取字節輸出流對象。
三、調用字節輸出流的write(byte[] buf)
或者write(int b)
向服務器發送指定數據。
四、記得關閉流。
服務器端:
一、建立ServerSocket
對象,並指定該應用程序的端口號,端口號必須和客戶端指定的端口號同樣。
二、使用ServerSocket
對象的accept()
方法來監聽客戶端發送過來的請求,返回值爲Socket對象。
三、調用Socket
對象的getInputStream()
方法獲取字節輸入流對象
四、調用字節輸入流對象的read(byte[] buf)
或read()
方法獲取數據。
五、記得關閉流。
實例:
客戶端向服務器端發送信息,並顯示在服務器端。
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 { //建立Socket對象,指定要發送到服務器端的IP地址,以及服務器端應用程序接收的端口號 //localhost表明本機IP地址 Socket client = new Socket("localhost",9000); //獲取輸出流,用於向服務器端發送數據 OutputStream os = client.getOutputStream(); os.write("Java is my friend !".getBytes()); System.out.println("信息已發送"); //關閉流 os.close(); client.close(); } }
Server類(服務器端)
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("--服務器端已開啓--"); //建立ServerSocket對象,這裏的端口號必須與客戶端的端口號相同 ServerSocket server = new ServerSocket(9000); //調用方法accept(),用來監聽客戶端發來的請求 Socket socket = server.accept(); //獲取輸入流對象 InputStream is = socket.getInputStream(); //讀取輸入流中的數據 int b = 0; while ((b =is.read()) != -1){ System.out.print((char)b); } //關閉流 is.close(); socket.close(); server.close(); } }
提示:在運行程序時,必定要先運行服務器端的程序代碼,再運行客戶端的程序代碼。由於客戶端要向服務器發送請求,前提是服務器端要處於開啓狀態。
Server類(服務器端)運行結果:
--服務器端已開啓--
Client類(客戶端)運行結果:
信息已發送
Client類(客戶端)運行後,Server類(服務器端)收到信息,運行結果:
--服務器端已開啓-- Java is my friend !
實例分析:
服務器端啓動後,服務器端的accept()
方法一直處於監聽狀態,直到客戶端鏈接了服務器,服務器端再從流中讀取客戶端發來的數據。
恕我直言,這是一個超級無敵簡單的單向通訊實例。
UDP使用數據報進行數據傳輸,沒有客戶端與服務器端之分,只有發送方與接收方,二者哪一個先啓動都不會報錯,可是會出現數據丟包現象。發送的內容有字數限制,大小必須限制在64k之內。
發送方與接收方實現步驟:
前提:建立一個項目,在項目中建立兩個模塊(model),一個模塊用來放發送方相關代碼,一個模塊用來放接收方相關代碼。
目錄結構以下圖
發送方:
一、建立DatagramSocket
對象,能夠指定應用程序的端口號,也能夠不指定。
二、準備須要發送的數據
三、建立DatagramPacket
對象,用來對發送的數據進行打包,須要指定發送內容、發送多少、發送到哪裏和接收方的端口號四個參數。
四、調用DatagramSocket
對象的send()
方法發送數據。
五、記得關閉流。
接收方:
一、建立DatagramSocket
對象,指定接收方的端口號,這個必須指定。
二、建立一個byte
類型數組,用來接收發送方發送過來的數據。
三、建立DatagramPacket
對象,準備接收數據。
四、調用DatagramSocket
對象的receive()
方法用於接收數據。
五、使用String
類的構造方法將byte類型
的數組中的數據轉化成String
類型並顯示。
六、記得關閉流。
實例:
發送方發送信息,接收方接收信息,並顯示。
Sender類(發送方)
package cn.tkrnet.Sender; import java.io.IOException; import java.net.*; public class Sender { public static void main(String[] args) throws IOException { //建立接受或發送的數據報套接字,並指定發送方的端口號爲7770 DatagramSocket ds = new DatagramSocket(7770); //端口號也能夠不指定 System.out.println("---發送方---"); //建立數據報對象,用來發送數據 byte[] b = "Java is my friend !".getBytes(); //8800爲接收方的端口號,netAddress.getByName("localhost")是獲取主機的IP地址 DatagramPacket dp = new DatagramPacket(b,b.length, InetAddress.getByName("localhost"),7788); ds.send(dp); //發送數據報 System.out.println("數據已發送"); //關閉流 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("---接收方---"); //建立數據報套接字對象,指定的端口號要和發送方發送數據的端口號相同 // (不是發送方的端口號7770,是發送方發送數據的端口號7788) DatagramSocket ds = new DatagramSocket(7788); //建立接收數據報的對象 byte[] b = new byte[1024]; DatagramPacket dp = new DatagramPacket(b,b.length); //接收數據 ds.receive(dp); System.out.println(new String(b,0,dp.getLength())); //關閉流 ds.close(); } }
提示:在運行程序時,先運行發送方程序,仍是先運行接收方程序都不會報錯,可是有可能會出現數據丟包,通常咱們都先運行接收方的程序代碼,再運行發送方的程序代碼。
Receiver類(接收方)運行結果:
---接收方---
Sender類(發送方)運行結果:
---發送方--- 數據已發送
Sender類(發送方)運行後,Receiver類(接收方)接收到信息,運行結果:
---接收方--- Java is my friend !
實例分析:
只有接收方先啓動運行,纔會存在端口號爲7788的程序,發送方纔能發送數據到指定端口號7788,接收方纔能接收數據。
不瞞你說,這也是個超級無敵簡單的單向通訊實例。
以上是我分享給你們的關於網絡通訊TCP協議與UDP協議的一些總結。
若是以爲還不錯的話,就點個贊和在看吧!
原文連接:https://blog.csdn.net/m0_4789...
版權聲明:本文爲CSDN博主「酷酷的猿」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處連接及本聲明。
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2021最新版)
2.終於靠開源項目弄到 IntelliJ IDEA 激活碼了,真香!
3.阿里 Mock 工具正式開源,幹掉市面上全部 Mock 工具!
4.Spring Cloud 2020.0.0 正式發佈,全新顛覆性版本!
以爲不錯,別忘了隨手點贊+轉發哦!