詳細介紹了java中的網絡通信機制,尤其是UDP協議,通過對UDP的基本使用進行舉例說明如何使用UDP進行數據的發送接收,並舉了兩個小demo說明UDP的使用注意事項。
UDP協議原理圖解:
UDP協議:需要借助於InetAddress來獲取設備的IP地址,以及姓名
1 import java.io.IOException; 2 import java.net.Inet4Address; 3 import java.net.InetAddress; 4 import java.net.UnknownHostException; 5 6 public class InetAddressDemo { 7 public static void main(String[] args) throws IOException { 8 // InetAddress address = InetAddress.getByName("10.129.123.23"); 9 InetAddress address = InetAddress.getByName("ooo-PC"); 10 // InetAddress address = InetAddress.getByName("lpp-PC"); 11 12 // 獲取該ip地址對象的IP地址和主機名 13 String name = address.getHostName(); 14 String ip = address.getHostAddress(); 15 16 System.out.println(name); 17 System.out.println(ip); 18 } 19 }
1 /* 2 * 網絡通訊三要素: 3 * 1.IP地址:InetAddress 網絡中設備的標識,不易記憶,可用主機名; 4 * 2.端口號:用於標識進程的邏輯地址,不同進程的標識傳輸協議通訊的規則;用於標識進程的邏輯地址,不同進程的標識, 5 * 有效端口:0~65535,其中0~1024系統使用或保留端口。 6 * 3.常見協議:TCP,UDP。 7 */ 8 9 /* 10 * UDP協議 11 * 將數據源和目的封裝成數據包中,不需要建立連接; 12 * 每個數據報的大小在限制在64k; 13 * 因無連接,是不可靠協議; 14 * 不需要建立連接,速度快 15 */ 16 17 /* 18 * Socket套接字: 19 * 網絡上具有唯一標識的IP地址和端口號組合在一起才能構成唯一能識別的 標識符套接字。 20 * Socket原理機制:通信的兩端都有Socket。 21 * 網絡通信其實就是Socket間的通信。 22 * 數據在兩個Socket間通過IO傳輸。 23 */ 24 25 26 27 28 //第一部分代碼是接收端,一般是先開接收端的代碼,再開發送端 29 //接收端代碼的創建步驟如下: 30 /* 31 * UDP協議接收數據: 32 * 1.創建接收端socket對象 33 * 2.創建一個數據包(接收數據的容器) 34 * 3.調用socket的對象的接收方法接收數據 35 * 4.解析數據,並顯示在控制台 36 * 5.釋放資源 37 */ 38 39 import java.io.IOException; 40 import java.net.DatagramPacket; 41 import java.net.DatagramSocket; 42 import java.net.InetAddress; 43 import java.net.SocketException; 44 45 /* 46 * 對於里面創建對象的部分進行優化直接鏈式編程 47 * java.net.BindException: Address already in use: Cannot bind 48 * 該端口已經被使用了,有可能是第二次調用或者第一次調用的時候該端口被其它程序使用。 49 */ 50 public class ReceiveDemo { 51 public static void main(String[] args) throws IOException { 52 // 創建接收端數socket對象,指定端口。 53 DatagramSocket ds = new DatagramSocket(10086); 54 // 接收數據 55 byte[] buf = new byte[1024]; 56 // int length = buf.length; 57 DatagramPacket dp = new DatagramPacket(buf, buf.length); 58 ds.receive(dp); // 將接受的數據放進dp數據報包中 59 // 解析數據,獲取IP地址以及數據報包中的內容 60 // InetAddress address = dp.getAddress(); 61 // String ip = address.getHostAddress(); 62 // byte[] bys = dp.getData(); 63 // int len = dp.getLength(); // 數據報包的實際長度 64 65 String ip = dp.getAddress().getHostAddress(); 66 String s = new String(dp.getData(), 0, dp.getLength()); 67 68 System.out.println(ip + ":--" + s); 69 70 // 釋放資源 71 ds.close(); 72 73 } 74 } 75 76 77 //---------------------------------------- 78 //下面是發送端的代碼,與上面分開在兩個類 79 80 import java.io.IOException; 81 import java.net.DatagramPacket; 82 import java.net.DatagramSocket; 83 import java.net.InetAddress; 84 import java.net.SocketException; 85 86 public class SendDemo { 87 public static void main(String[] args) throws IOException { 88 // 發送端socket對象 89 DatagramSocket ds = new DatagramSocket(); 90 91 // 數據打包 92 byte[] bys = "java".getBytes(); 93 // int len = bys.length; 94 // InetAddress address = InetAddress.getByName("lpp-PC"); 95 // int port = 10086; 96 97 DatagramPacket dp = new DatagramPacket(bys, bys.length, 98 InetAddress.getByName("lpp-PC"), 10086); 99 100 // 發送數據 101 ds.send(dp); 102 103 // 釋放資源 104 ds.close(); 105 } 106 }
1 /* 2 * 多線程實現在一個代碼里面姐發送又接受數據 3 * 在發送端從鍵盤錄入數據,一直讀到886結束數據的錄入發送,鍵盤錄入一句就接受一句,接收端一直開着等着數據的發送。 4 */ 5 6 //首先是main方法 7 8 import java.io.IOException; 9 import java.net.DatagramSocket; 10 import java.net.SocketException; 11 12 /* 13 * 通過多線程 14 */ 15 public class chatRoomDemo { 16 public static void main(String[] args) throws IOException { 17 // 接收端,發送端socket 18 DatagramSocket dsSend = new DatagramSocket(); 19 DatagramSocket dsReceive = new DatagramSocket(10086); 20 21 SendThread st = new SendThread(dsSend); 22 ReceiveThread rt = new ReceiveThread(dsReceive); 23 24 // 線程開啟 25 Thread sendThread = new Thread(st); 26 Thread receiverThread = new Thread(rt); 27 28 sendThread.start(); 29 receiverThread.start(); 30 } 31 } 32 33 //-------------------------------------------- 34 //接收端線程的創建 35 import java.io.IOException; 36 import java.net.DatagramPacket; 37 import java.net.DatagramSocket; 38 39 public class ReceiveThread implements Runnable { 40 private DatagramSocket ds; 41 42 public ReceiveThread(DatagramSocket ds) { 43 // 通過構造方法進行初始化 44 this.ds = ds; 45 } 46 47 @Override 48 public void run() { 49 // TODO Auto-generated method stub 50 while (true) { 51 try { 52 byte[] buf = new byte[1024]; 53 DatagramPacket dp = new DatagramPacket(buf, buf.length); 54 ds.receive(dp); 55 56 String ip = dp.getAddress().getHostAddress(); 57 58 String s = new String(dp.getData(), 0, dp.getLength()); 59 60 System.out.println(ip + "--->" + s); 61 } catch (IOException e) { 62 e.printStackTrace(); 63 } 64 } 65 } 66 } 67 68 //--------------------------------------- 69 //發送端線程的創建 70 71 import java.io.BufferedReader; 72 import java.io.IOException; 73 import java.io.InputStream; 74 import java.io.InputStreamReader; 75 import java.net.DatagramPacket; 76 import java.net.DatagramSocket; 77 import java.net.InetAddress; 78 79 public class SendThread implements Runnable { 80 private DatagramSocket ds; 81 82 public SendThread(DatagramSocket ds) { 83 this.ds = ds; 84 } 85 86 @Override 87 public void run() { 88 // TODO Auto-generated method stub 89 try { 90 BufferedReader br = new BufferedReader(new InputStreamReader( 91 System.in)); 92 String line = null; 93 while ((line = br.readLine()) != null) { 94 if ("886".equals(line)) { 95 break; 96 } 97 byte[] buf = line.getBytes(); 98 DatagramPacket dp = new DatagramPacket(buf, buf.length, 99 InetAddress.getByName("lpp-PC"), 10086); 100 101 ds.send(dp); 102 } 103 } catch (IOException e) { 104 e.printStackTrace(); 105 } 106 // //釋放資源 107 // ds.close(); 108 } 109 110 }