1. 程式人生 > 其它 >Java網路程式設計:使用DatagramSocket實現簡單聊天功能

Java網路程式設計:使用DatagramSocket實現簡單聊天功能

使用DatagramSocke和DatagramPacket實現簡單的聊天室功能,具體如下:

  • 使用DatagramSocke開啟埠用來接收和傳送資料
  • 使用DatagramPacket對資料進行打包
  • 實現Runnable介面啟動一個接收執行緒和一個傳送執行緒
  • 使用UDP協議進行通訊

UDP協議通訊類似於發簡訊功能,無需握手連線,實現較為簡單。

傳送執行緒

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;

public class UdpSend implements Runnable{
    DatagramSocket socket = null;
    BufferedReader reader = null;
    private int fromPort;
    private String toIP;
    private int toPort;

    public UdpSend(int fromPort, String toIP, int toPort) throws Exception {
        this.fromPort = fromPort;
        this.toIP = toIP;
        this.toPort = toPort;

        socket = new DatagramSocket(fromPort);
        reader = new BufferedReader(new InputStreamReader(System.in));
    }

    @Override
    public void run() {
        while(true) {
            try {
                //讀取控制檯資料
                String data = reader.readLine();
                byte[] datas = data.getBytes();
                //建立包
                DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress(this.toIP, this.toPort));
                //傳送包
                socket.send(packet);
                if(data.equals("bye")){//取消傳送條件
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }socket.close();
    }
}

接收執行緒

public class UdpReceive implements Runnable {
    DatagramSocket socket = null;
    private int ownPort;
    private String msgFrom;

    public UdpReceive(int ownPort, String msgFrom) throws Exception {
        this.ownPort = ownPort;
        this.msgFrom = msgFrom;
        socket = new DatagramSocket(ownPort);
    }
    @Override
    public void run() {
        while (true) {
            try {
                //接受資料包
                byte[] buffer = new byte[1024];
                DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
                socket.receive(packet);//阻塞接收
                byte[] data = packet.getData();
                int len = packet.getLength();

                String receiveData = new String(data, 0, len);
                System.out.println(msgFrom+":"+receiveData);
                if (receiveData.equals("bye")) {
                    break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        socket.close();
    }
}

學生端

public class student {
    public static void main(String[] args) throws Exception {
        new Thread(new UdpReceive(7777,"老師")).start();
        new Thread(new UdpSend(8888,"localhost",9090)).start();
    }
}

老師端

public class teacher {
    public static void main(String[] args) throws Exception {
        new Thread(new UdpReceive(9090,"學生")).start();
        new Thread(new UdpSend(9999,"localhost",7777)).start();
    }
}

遇到的Bug

在控制檯顯示資料包時,資料後面會跟許多空格:

經查詢原因,發現是由於收到資料包轉換為String型別時資料長度設定錯誤:

//錯誤示範

byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);//阻塞接收

byte[] data = packet.getData();//獲取資料包中的資料
String receiveData = new String(data, 0, data.length);//此處資料長度不可使用陣列的長度


System.out.println(msgFrom+":"+receiveData);
//正確程式碼

byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);//阻塞接收

byte[] data = packet.getData();
int len = packet.getLength();//使用DatagramPacket的getLength()方法獲取資料的長度。
String receiveData = new String(data, 0, len);//使用正確的長度引數即可避免錯誤。

System.out.println(msgFrom+":"+receiveData);
Seven times have I despised my soul: The first time when I saw her being meek that she might attain height. The second time when I saw her limping before the crippled. The third time when she was given to choose between the hard and the easy, and she chose the easy. The fourth time when she committed a wrong, and comforted herself that others also commit wrong. The fifth time when she forbore for weakness, and attributed her patience to strength. The sixth time when she despised the ugliness of a face, and knew not that it was one of her own masks. And the seventh time when she sang a song of praise, and deemed it a virtue.