1. 程式人生 > >《網際網路程式設計(Java)》——課程筆記7:UDP套接字程式設計(無連線)

《網際網路程式設計(Java)》——課程筆記7:UDP套接字程式設計(無連線)

學會使用UDP套接字來實現網路應用程式設計。

UDP通訊特點:

    (1) UDP有別於TCP,有自己獨立的套接字(IP+PORT),它們的埠號不衝突;

    (2) UDP 通訊前通常[不]需要連線;

    (3) 基於使用者資料報文(包)讀寫;

    (4) UDP通訊一般用於線路質量好的環境,如區域網內。

1.程式設計第一步:建立UDPClient.java程式

UDPClient.java源程式見下面。

(1)UDP套接字類: DatagramSocket

     不像TCP通訊有客戶套接字Socket和伺服器套接字ServerSocket兩種,而UDP套接字只有一種DatagramSocket,不區分客戶套接字和伺服器套接字。

     UDP套接字的兩個重要方法是:

     傳送網路資料用:DatagramSocket.send(packet); //傳送一個數據包

     接收網路資料用:DatagramSocket.receiver(packet);//接收一個數據包

 其中packet屬於 DatagramPacket報文類的一個例項物件,使用者資料封裝在packet中。

(2)UDP資料報文類:DatagramPacket。

      TCP傳送資料是基於位元組流的,而UDP傳送資料是基於報文DatagramPacket,網路中傳遞的UDP資料都要封裝在報文中。

     報文類的兩個重要方法是:

     Byte[] b=DatagramPacket.getData();//從報文中取資料

     DatagramPacket.setData(String msg);//往報文中填充資料

2.程式設計第二步:建立UDPClientJFrame.java程式

   使用者介面如圖1所示。

圖1 UDP使用者介面

(1)   在“連線”按鈕中例項化UDPClient物件,並啟動接收資訊的“讀執行緒”;

(2)   在“傳送”按鈕中設定傳送資訊的動作程式碼;

(3)   在“退出”按鈕中設定退出程式執行程式碼。

3.程式設計第三步:建立UDPServer.java

程式

   根據UDPClient.java程式,建立對應的UDPServer伺服器程式。伺服器程式的功能是接收使用者資訊,並能自動返回使用者資訊。

   完成UDPServer伺服器程式後,啟動你的伺服器,首先能實現和自己的客戶端成功對話。

部分程式碼:

UDPClient.java:

public class UDPClient {
  private int remotePort;
  private InetAddress  remoteIP;
  private DatagramSocket socket; //UDP套接字 
 
  public UDPClient(String ip,String port)throws IOException{
      this.remotePort=Integer.parseInt(port);
      this.remoteIP=InetAddress.getByName(ip);
     
      //建立一個UDP套接字,與本地任意一個未使用的UDP埠繫結
      socket=new DatagramSocket(); 
      //與本地一個固定的UDP埠繫結
      //socket=new DatagramSocket(1***);       
  }
  
  //定義一個數據的傳送方法。
  public void send(String msg){
    try {
        //先準備一個待發送的資料報
        byte[] outputData=msg.getBytes("GB2312");
        //構建一個數據報文。  
        DatagramPacket outputPacket=new DatagramPacket(outputData,
                                 outputData.length,remoteIP,remotePort);
        //給UDPServer傳送資料報
        socket.send(outputPacket);  //給UDPServer傳送資料報
    } catch (IOException ex) { }
  }
 
  //定義一個數據的接收方法。
  public String receive(){//throws IOException{
    String msg;
    //先準備一個空資料報文
    DatagramPacket inputPacket=new DatagramPacket(new byte[512],512);
      try {
          //阻塞語句,有資料就裝包,以裝完或裝滿為此.
          socket.receive(inputPacket);
          //從報文中取出位元組資料並裝飾成字元。
          msg=new String(inputPacket.getData(),
                         0,inputPacket.getLength(),"GB2312");
      } catch (IOException ex) {
        msg=null;
      }
    return msg;
  }
 
  public void close(){
    if(socket!=null)  
       socket.close();//釋放本地埠.
  }
}
 

連線按鈕:

例項化UDPClient物件,並啟動接收資訊的“讀執行緒”;


    //連線按鈕
    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // TODO add your handling code here:
        ip = jTextField1.getText();
        port = jTextField2.getText();
        try
        {
            //例項化
            client = new UDPClient(ip,port);
            
          
           //同時例項化讀執行緒
            Thread receiver = new Thread()//用一個執行緒專門來接收資訊
            {
                public void run()
                {
                    String msg = null;
                    while((msg = client.receive())!=null)
                    {
                        jTextArea1.append(msg + "\n");
                    }
                    jTextArea1.append("對話方塊已關閉! \n");
                }
            };
            
            receiver.start();//啟動該執行緒
        
            
            
            
        }catch(Exception e)
        {
            e.printStackTrace();
        }
        
    }                                        

    

伺服器:

ublic class UDPServer {
    private final static int DEFAULT_PORT = 8800;
    private final static int MAX_PACKET_SIZE = 512;
    public static void main(String args[])
    {
        int port = DEFAULT_PORT;
        byte[]  buffer = new byte[MAX_PACKET_SIZE];
        try
        {
            DatagramSocket server = new DatagramSocket(port);
            DatagramPacket packet = new DatagramPacket(buffer,buffer.length);
            System.out.println("UDP server 啟動在8800埠");
            while(true)
            {
                server.receive(packet);
                String s = new String(packet.getData(),packet.getOffset(),packet.getLength(),"GB2312");
                System.out.println(packet.getAddress() + "  at port: " + packet.getPort() + "says: \n" + s);
                
                
                
                 //先準備一個待發送的資料報
       //     byte[] outputData = msg.getBytes("GB2312");
            //構建一個數據報文
                String studentId = "201";
                String studentName = "";
                
                s ="  " + studentId + "-" + studentName +  "-" + new Date().toString() +"-"+ s;
            
                byte[] outputData = s.getBytes("GB2312");
                 DatagramPacket outputPacket = new DatagramPacket(outputData, outputData.length, packet.getAddress(), packet.getPort());
            
            //給UDPServer傳送資料報
            server.send(outputPacket);//傳送資料報
                System.out.println("伺服器已經發送了資料給計分伺服器");
                
                
                //設定以後需要接受的長度
                packet.setLength(buffer.length);
            }
            
            
        }catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}

先啟動伺服器,再啟動客戶端。