區域網聊天室
阿新 • • 發佈:2018-11-27
區域網聊天室需要完成以下幾個功能:
* 1.區域網中各主機都能參與到聊天室中聊天,即可以接發訊息,其中接受可以接受每臺主機發送的訊息,傳送的訊息每臺主機都能收到
* 2.簡陋介面
實現思想:
1.先實現介面的設計。建立自己的J711ChatRoom()類來繼承JFrame()類。即可隨意編寫介面。
2.傳送訊息採用多播資料通道MulticastSocket,並且利用joinGroup()方法給其指定一個多播地址groupIp。每個主機都用DatagramPacket來打包自己的訊息,然後將資料包傳送到多播地址,改資料包得從指定的埠傳送,然後MulticastSocket就可以呼叫send方法把主機發送的資料包給廣播出去。
3.接收訊息採用執行緒來實現,因為接受訊息是實時進行的,所以要實現接受的同時還能傳送訊息,則可以利用執行緒的阻塞來完成。首先在指定埠中開啟多播通道MulticastSocket,然後利用joinGroup()方法給其指定一個多播地址groupIp。然後利用receive()方法從多播通道中獲取資料包。此處獲取資料包的程式碼處於死迴圈狀態,使其保持一直接受訊息的狀態。然後將接受到的訊息append到文字域中。
一些細節:
setLayout(null); // 設定佈局方式,為null則代表控制元件可以根據自身設定的位置任意擺放
setLocationRelativeTo(null); // 引數為null此視窗置於螢幕的中央
ms.joinGroup(“/226.81.9.8");// 地址前要加一個反斜槓
以下是執行效果:
import java.awt.Color;
import java.awt.Font;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.border.LineBorder;
public class J711ChatRoom extends JFrame{
public static void main(String[] args) {
new J711ChatRoom();
}
private JLabel label1;
private JTextArea area1;// 文字域
private JTextArea area2;// 文字域
private JButton button;
private Insets margin = new Insets(10, 10, 10, 10); // 讓發出去的訊息與邊框隔開10個單位
public J711ChatRoom(){
setTitle("聊天室");
setSize(500, 500);
setLocationRelativeTo(null); // 引數為null此視窗置於螢幕的中央
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
// 設定佈局方式,為null則代表控制元件可以根據自身設定的位置任意擺放
setLayout(null);
initUI();
setVisible(true);
}
private void initUI() {
label1 = createJLabel("J711聊天室", 180, 20, 200, 30);
area1 = createJTextArea(50, 60, 395, 230);
area1.setMargin(margin);// 前面空兩格
area2 = createJTextArea(50, 300, 395, 100);
button = new JButton("傳送");
button.setBounds(345, 410, 100, 30);
new Receiver().start();
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Send(area2.getText());
area2.setText("");
}
});
add(label1);
add(area1);
add(area2);
add(button);
}
/**************傳送訊息***************/
public void Send(String msg){
try {
//建立多播資料報通道 (發資料) DatagramPacket
MulticastSocket ms = new MulticastSocket();
//客戶端要接到訊息都必須通過下面這個地址
InetAddress groupIp = InetAddress.getByName("226.81.9.8");
ms.joinGroup(groupIp);//將socket通道加入多播地址
//將需要傳送的資料打包為資料報包
String content = msg;//廣播內容
//資料包
DatagramPacket dp = new DatagramPacket(content.getBytes(), content.getBytes().length);
//先把訊息發到多播地址
dp.setAddress(groupIp);
dp.setPort(2426);
//傳送包裹
ms.send(dp);
} catch (IOException e) {
e.printStackTrace();
}
}
/*************接收訊息**************/
public class Receiver extends Thread{
@Override
public void run() {
try {
int count = 0;
//佔據指定的埠開啟多播通道
MulticastSocket ms = new MulticastSocket(2426);
InetAddress groupIp = InetAddress.getByName("226.81.9.8");
ms.joinGroup(groupIp);
String s = "";
Date date = null;
SimpleDateFormat sdf;
byte[] b = new byte[1024];
//宣告資料報包,用於接收廣播資訊
DatagramPacket dp = new DatagramPacket(b, b.length);
while(true){
count++;
if (count % 8 == 0) area1.setText("");
date = new Date();// 獲取當前時間即訊息傳送的時間
sdf = new SimpleDateFormat("HH:mm:ss");
dp = new DatagramPacket(b, b.length);
ms.receive(dp);
s = new String(dp.getData(), dp.getOffset(), dp.getLength());
s = dp.getAddress() + " "+ sdf.format(date) + "\n" + s + "\n";
area1.append(s);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public JTextArea createJTextArea(int x, int y, int w, int h){
JTextArea area = new JTextArea();
area.setBounds(x, y, w, h);
area.setLineWrap(true); // 自動換行
area.setBorder(new LineBorder(new Color(129, 152, 48)));
return area;
}
public JLabel createJLabel(String name, int x, int y, int w, int h){
JLabel label = new JLabel(name);
//設定控制元件的邊界 x y 寬 高
label.setBounds(x, y, w, h);
label.setHorizontalTextPosition(JLabel.CENTER);
label.setFont(new Font("楷體", Font.BOLD, 20));
label.setForeground(Color.RED);
return label;
}
}