【Socket編程】經過Socket實現UDP編程

經過Socket實現UDP編程

UDP通訊:html

一、UDP協議(用戶數據報協議)是無鏈接、不可靠、無序的。編程

二、UDP協議以數據報做爲數據傳輸的載體。小程序

三、使用UDP進行數據傳輸時,首先須要將要傳輸的數據定義成數據報(Datagram),在數據報中指明所要達到的Socket(主機地址和端口號),而後在將數據報發生出去。數組

四、相關操做類:安全

  • DatagramPacket:表示數據報包
  • DatagramSocket:進行端到端通訊的類

1、DatagramPacket&DatagramSocket類的經常使用方法

<DatagramPacket類>服務器

構造方法:網絡

1 DatagramPacket(byte[] buf,int length)//接受長度爲length的數據包
3 DatagramPacket(byte[] buf,int length,InetAddress address,int port)//將指定長度的字節發生到指定主機的指定端口 

<DatagramSocket類>多線程

構造方法:socket

1  DatagramSocket();
2  DatagramSocket(int port,InetAddress laddr);

經常使用方法:測試

1  close();//關閉DatagramSocket
2  getInetAddress();//獲取地址
3  getPort();//獲取端口號
4  send(DatagramPacket p);//今後套接字發送數據包
5  recrive(DatagramPacket p);//今後套接字接收數據包

2、編程實現基於UDP的用戶登陸小程序

經過寫一個用戶登陸的小程序,來直觀瞭解基於UDP的Socket通訊的工做過程,首先咱們得知道在客戶端和服務器通訊時,二者的運做流程是如何的,先從服務器入手。

服務器端實現步驟:

一、建立DatagramSocket,指定端口號

二、建立DatagramPacket

三、接收客戶端發送的數據信息

四、讀取數據

那麼用戶登陸的測試案例的服務器端類能夠這樣(待完善):

 1 public static void main(String[] args) throws IOException {
 2         // TODO Auto-generated method stub
 3         
 4         try {
 5             //1.建立服務器端DatagramSocket,指定端口
 6             DatagramSocket ds=new DatagramSocket(8080);
 7             //2.建立數據報DatagramPacket,用於接收客戶端發送的數據
 8             byte[] data=new byte[1024];//建立字節數組,指定接受的數據報大小
 9             DatagramPacket dp=new DatagramPacket(data, data.length);
10             //3.接收客戶端發送的數據
11             ds.receive(dp);//此方法在接收到數據報以前會一直阻塞
12             //4.讀取數據
13             //String info=Arrays.toString(data);
14             String info=new String(data, 0, dp.getLength());
15             System.out.println("我是服務器,客戶端說:"+info);
16         } catch (SocketException e) {
17             // TODO Auto-generated catch block
18             e.printStackTrace();
19         }
20     }

接着咱們看一下客戶端的運做過程,其實和服務器端差很少,可是其中的區別仍是要清楚的。

客戶端實現步驟:

一、定義發送信息

二、建立DatagramPacket:包含將要發送信息

三、建立DatagramSocket

四、發送數據

那麼用戶登陸的測試案例的客戶端類能夠這樣(待完善):

 1 public static void main(String[] args) throws IOException {
 2         // TODO Auto-generated method stub
 3         //1.定義服務器的地址、端口號、數據
 4         InetAddress add=InetAddress.getByName("localhost");
 5         int port=8080;
 6         byte[] data="用戶名:admin;密碼:123".getBytes();
 7         //2.建立數據報,包含了發送的相關信息
 8         DatagramPacket ap=new DatagramPacket(data, data.length, add, port);
 9         //3.建立DatagramSocket對象
10         DatagramSocket ds=new DatagramSocket();
11         //4.向服務器端發送數據報
12         ds.send(ap);
13         
14     }

這樣服務端和客戶端就能進行最簡單的通訊了,目前這個還不能實現交互,下面會講二者的交互。

運行一下,看看服務器端是否能接收到客戶端發送的信息了呢...

分別啓動服務器和客戶端,注意必須先啓動服務器再啓動客戶端,不然客戶端找不到資源報錯:


完善用戶登陸之服務器響應客戶端

在上述的例子中,服務器和客戶端僅僅只是相互能夠通訊,但服務器對於接收到的客戶端信息並無向客戶端響應,客戶端沒有接收到服務器端的任何信息,這明顯是不完善不友好的,在這裏將對剛剛的例子進行完善,完成服務器對客戶端的響應。

修改後的服務器端:

 1 public static void main(String[] args) throws IOException {
 2         // TODO Auto-generated method stub
 3         
 4         try {
 5             /*
 6              * 接收客戶端發送的數據
 7              */
 8             //1.建立服務器端DatagramSocket,指定端口
 9             DatagramSocket ds=new DatagramSocket(8080);
10             //2.建立數據報DatagramPacket,用於接收客戶端發送的數據
11             byte[] data=new byte[1024];//建立字節數組,指定接受的數據報大小
12             DatagramPacket dp=new DatagramPacket(data, data.length);
13             //3.接收客戶端發送的數據
14             System.out.println("服務器端已啓動,等待客戶端發送數據...");
15             ds.receive(dp);//此方法在接收到數據報以前會一直阻塞
16             //4.讀取數據
17             //String info=Arrays.toString(data);
18             String info=new String(data, 0, dp.getLength());
19             System.out.println("我是服務器,客戶端說:"+info);
20             /*
21              * 響應客戶端
22              */
23             //1.定義客戶端的地址、端口號、數據
24             InetAddress add=dp.getAddress();
25             int port=dp.getPort();
26             byte[] data2="歡迎您!".getBytes();
27             //2.建立數據報,包含響應的數據信息
28             DatagramPacket dp2=new DatagramPacket(data2, data2.length, add, port);
29             //3.響應客戶端
30             ds.send(dp2);
31             //4.關閉資源
32             ds.close();
33             
34             
35         } catch (SocketException e) {
36             // TODO Auto-generated catch block
37             e.printStackTrace();
38         }
39     }

修改後的客戶端:

 1 public static void main(String[] args) throws IOException {
 2         // TODO Auto-generated method stub
 3         /*
 4          * 向服務器發送數據
 5          */
 6         //1.定義服務器的地址、端口號、數據
 7         InetAddress add=InetAddress.getByName("localhost");
 8         int port=8080;
 9         byte[] data="用戶名:admin;密碼:123".getBytes();
10         //2.建立數據報,包含了發送的相關信息
11         DatagramPacket ap=new DatagramPacket(data, data.length, add, port);
12         //3.建立DatagramSocket對象
13         DatagramSocket ds=new DatagramSocket();
14         //4.向服務器端發送數據報
15         ds.send(ap);
16         /*
17          * 接收服務器端的響應
18          */
19         //1.建立數據報DatagramPacket,用於接收服務器發送的數據
20         byte[] data2=new byte[1024];
21         DatagramPacket dp2= new DatagramPacket(data2, data2.length);
22         //2.接收響應
23         ds.receive(dp2);
24         //3.讀取數據
25         String info=new String(data2, 0, dp2.getLength());
26         System.out.println("我是客戶端,服務器說:"+info);
27         //4.關閉資源
28         ds.close();
29     }

運行結果:

3、使用多線程實現多客戶端的通訊

 應用多線程來實現服務器與多客戶端之間的通訊。<關於多線程更多的內容之後再總結>

多線程基本步驟:

1.服務器端建立DatagramSocket,循環調用receive()等待客戶端發送數據報。

2.客戶端建立一個DatagramSocket發送數據報到服務器端。

3.服務器端接收客戶端的數據報,建立DatagramPacket與該客戶創建專線接收數據報。

4.創建交互數據報在一個單獨的線程上對話。

5.服務器端繼續等待新的數據報。

 ------------------------------------------------------------------------------

下面再將上述的例子修改爲多線程的通訊

新建一個服務器線程處理類UDPServerThread,該類繼承Thread類:

 

 1 /*
 2  * 服務器線程處理類
 3  */
 4 public class UDPServerThread extends Thread {
 5     DatagramSocket ds=null;
 6     DatagramPacket dp=null;
 7     public UDPServerThread(DatagramSocket ds,DatagramPacket dp){
 8         this.ds=ds;
 9         this.dp=dp;
10     }
11     
12     
13     public void run(){
14         
15     
16         try {
17             /*
18              * 接收客戶端發送的數據
19              */
20             
21             //4.讀取數據
22             //String info=Arrays.toString(data);
23             byte[] data=dp.getData();
24             String info=new String(data, 0, dp.getLength());
25             System.out.println("我是服務器,客戶端說:"+info);
26             /*
27              * 響應客戶端
28              */
29             //1.定義客戶端的地址、端口號、數據
30             InetAddress add=dp.getAddress();
31             int port=dp.getPort();
32             byte[] data2="歡迎您!".getBytes();
33             //2.建立數據報,包含響應的數據信息
34             DatagramPacket dp2=new DatagramPacket(data2, data2.length, add, port);
35             //3.響應客戶端
36             ds.send(dp2);
37             
38         
39         } catch (IOException e) {
40             // TODO Auto-generated catch block
41             e.printStackTrace();
42         }
43         
44     }
45 }

服務器端:

 1 /*
 2  * 服務器端
 3  */
 4 public class UDPSever {
 5 
 6     public static void main(String[] args) throws IOException {
 7         // TODO Auto-generated method stub
 8 
 9         try {
10 
11             // 1.建立服務器端DatagramSocket,指定端口
12             DatagramSocket ds = new DatagramSocket(8080);
13             System.out.println("服務器即將啓動,等待客戶端的鏈接...");
14             byte[] data = new byte[1024];
15             // 記錄客戶端的數量
16             int count = 0;
17             // 循環偵聽等待客戶端的鏈接
18             while (true) {
19                 DatagramPacket dp = new DatagramPacket(data, data.length);
20                 ds.receive(dp);
21                 // 建立一個新的線程
22                 UDPServerThread udp = new UDPServerThread(ds, dp);
23                 // 啓動線程,執行與客戶端的交互
24                 udp.start();
25                 count++;
26                 System.out.println("此時客戶端數量爲:" + count);
27                 InetAddress add = dp.getAddress();
28                 System.out.println("當前客戶端的ip地址爲" + add.getHostAddress());
29             }
30 
31         } catch (SocketException e) {
32             // TODO Auto-generated catch block
33             e.printStackTrace();
34         }
35     }
36 
37 }

多個客戶端的運行結果:

這樣一個簡單的多線程UDP通訊就完成了。

4、UDP和TCP

<解 惑>TCP和UDP編程都用在什麼地方?

<回 答>網絡通訊,例如QQ客戶端和服務器間的通訊。

TCP是面向鏈接的、可靠的,若是對通訊數據的可靠性要求比較高,確保數據對方能夠收到,可使用TCP。

UDP是無鏈接的,在通訊前不會預先創建鏈接,沒法保證可靠性,通常用於對數據可靠性要求不是那麼高的場合。

 

<解 惑>UDP和TCP相比較有什麼優缺點?

<回 答>UDP相較於TCP,不須要進行復雜的設定輸入輸出流,只須要設定數據報,即DatagramPacket。而TCP的發送以及接收消息,是經過socket.getInputStream()或者getOutputStream()方法,而UDP是直接設置了,DatagramSocket,經過其send()或者receive()方法來接收或發送消息。TCP的關鍵組成有server端的ServerSocket.accept()方法,這個方法是直到接收到了客戶端的鏈接纔會返回一個Socket,用於接下來的輸入和輸出。

因此說,TCP的數據傳輸是須要提早鏈接、三方握手,數據傳輸很是安全;

UDP是不須要提早鏈接的,無需等待對方回答,因此不保證數據不丟失。

---------------點擊查看更多關於Socket信息------------------

相關文章
相關標籤/搜索