常見的通訊協議有udp和tcp。
先來簡單了解一下這兩個協議各自的特點:
UDP:
--將數據及源、目的封裝在數據包中,不需要建立連接;
--每個數據包的大小限制在64k以內;
--因無連接,是不可靠協議;
--不需要建立連接,所以傳輸速度快,但是容易丟失數據;
總之:Udp是面向無連接的通訊協議,傳輸數據時,不管對端服務是否啟動,直接發送。
日常中使用Udp技術的軟件有:飛秋、視頻會議等;
TCP:
--建立連接,形成傳輸數據的通道;
--在連接中進行大的數據量傳輸;
--通過三次握手完成連接,是可靠協議;
--必須建立連接,效率會稍低;
日常中使用Tcp技術的軟件有:打電話的場景,下載。
了解了以上兩種常用的通訊協議之后,再認識一下網絡通訊的機制:Socket
Socket:
--就是為網絡服務提供的一種機制;
--通信的兩端都有Socket;
--網絡通信其實就是Socket建的通信;
--數據再兩個Socket間通過 IO 傳輸。
也可以這樣理解:Socket就像連接航線兩端的港口。
============================優雅的分割線============================
我們在實現網絡編程時,最重要的是要理解並掌握其實現的原理:
下面先講解一下Udp傳輸的原理:
--1、Udp傳輸技術基於 DatagramSocket 與 DatagramPacket對象;
--2、建立發送端、接收端;
--3、建立數據包;
--4、調用Socket的發送接收方法;
--5、關閉Socket;
--6、發送端和接收端是兩個獨立的運行程序;
下面來看一個簡單Udp傳輸Demo:
//發送端:

package com.shindo.java.udp; import java.net.*; /** * 需求:通過Udp傳輸方式,將一段文字數據發送 出去; * * 思路: * 1、建立UdpSocket服務; * 2、提供數據,並將數據封裝到數據包中; * 3、通過Socket服務的發送功能,將數據包發出去 * 4、關閉資源 */ public class UdpSend { public static void main(String[] args)throws Exception{ //1、創建Udp服務,通過DatagramSocket對象 DatagramSocket ds = new DatagramSocket(); //2、確定數據,並封裝成數據包 byte[] buf = "This's UdpSend test first Demo".getBytes(); /*DatagramPacket(byte[] buf, int length, InetAddress address, int port) 構造數據報包,用來將長度為 length 的包發送到指定主機上的指定端口號。 */ DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),11010); //3、通過Socket服務,將已有的數據包發送出去,通過send方法 ds.send(dp); Thread.sleep(10000); //4、關閉資源 ds.close(); } }
//接收端:

package com.shindo.java.udp; import java.net.*; /** * 需求:定義一個應用程序,用於接收Udp協議傳輸的數據並處理 * * 思路: * 1、定義UdpSocket服務,並監聽一個端口; * 2、定義個數據包,因為要存儲接收到的字節數據--數據包對象中封裝了提取字節數據信息的方法; * 3、通過Socket服務的receive方法將收到的數據存入已定義好的數據包中; * 4、通過數據包對象的特有功能,將這些不同的數據去除,打印在控制台上; * 5、關閉資源 */ public class Udpreceive { public static void main(String[] args)throws Exception{ //創建UdpSocket,建立端點 DatagramSocket ds = new DatagramSocket(11010); while(true){ //2、定義數據包用於存儲數據 byte[] buf = new byte[1024]; /* * DatagramPacket(byte[] buf, int length) 構造 DatagramPacket,用來接收長度為 length 的數據包。 */ DatagramPacket dp = new DatagramPacket(buf,buf.length); //3、通過數服務的receive方法,將收到的數據存入數據包中 ds.receive(dp); //4、通過數據包的方法獲取其中的數據 String ip = dp.getAddress().getHostAddress(); System.out.println(ip + "..........is connected"); String data = new String(dp.getData(),0,dp.getLength());//只打印接收數據的長度,不打印全部緩沖流 System.out.println(data); int port = dp.getPort(); System.out.println("port:" + port); //5、關閉資源 ds.close(); } } }
運行結果:
127.0.0.1..........is connected This's UdpSend test first Demo port:52793 Exception in thread "main" java.net.SocketException: Socket closed at java.net.PlainDatagramSocketImpl.receive0(Native Method) at java.net.PlainDatagramSocketImpl.receive(PlainDatagramSocketImpl.java:136) at java.net.DatagramSocket.receive(DatagramSocket.java:725) at com.shindo.java.udp.Udpreceive.main(Udpreceive.java:28)
============================優雅的分割線============================
上面的Demo我們可以看到只是實現了簡單的客戶端發送,服務端讀取並展示的過程。而且客戶端只能發送特定的內容:This's UdpSend test first Demo
我們下面就把客戶端改寫一下,讓它能夠讀取鍵盤錄入的信息:
//發送端:使用鍵盤錄入信息

package com.shindo.java.udp; import java.io.*; import java.net.*; /** * 需求:實現發送信息的鍵盤錄入 */ public class UdpSendKeyboard { public static void main(String[] args) throws Exception{ DatagramSocket ds = new DatagramSocket(); BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); String line = null; while((line = bufr.readLine()) != null ){ if("byebye".equals(line)) break; byte[] buf = line.getBytes(); DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),11010); ds.send(dp); } ds.close(); } }