局域网聊天工具

小绵羊 2011-09-08 06:15:13
下午在公司闲的蛋疼,花了2个小时整了个局域网的聊天工具玩。界面模仿飞鸽传书,基于UDP协议,只有最基本的聊天功能。代码结构也比较乱,有兴趣的可以拿去玩玩。

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import java.util.Map;
import java.util.UUID;

import javax.swing.JFrame;

import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JButton;
import javax.swing.border.EtchedBorder;
import javax.swing.table.DefaultTableModel;

import java.awt.SystemColor;
import javax.swing.ScrollPaneConstants;
import java.awt.Color;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JLabel;

public class Msg extends JFrame {
private static final long serialVersionUID = 3170335398335303363L;
private String uname = "qq";

private DatagramSocket server;// UDP
private InetAddress broadcastAddress;// 廣播地址
private int port;// 監聽端口

private final Map<String, UserInfo> userTable = new Hashtable<String, UserInfo>();// 用戶列表
private final String guid = UUID.randomUUID().toString().replace("-", "").toUpperCase();// 本機唯一標識

private JTable table;
private JTextArea textArea;
private JLabel lblNewLabel_1;

public Msg() throws SocketException {
this(5413);
}

public Msg(int port) throws SocketException {
this.port = port;

getContentPane().setLayout(null);
getContentPane().setBackground(SystemColor.control);

JButton btnNewButton = new JButton("刷新");
btnNewButton.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
refresh();
}
});
btnNewButton.setBackground(SystemColor.control);
btnNewButton.setBounds(299, 119, 83, 28);
getContentPane().add(btnNewButton);

JScrollPane scrollPane = new JScrollPane();
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setBounds(12, 12, 275, 135);
getContentPane().add(scrollPane);

table = new JTable(new DefaultTableModel(new Object[][] { { null, null, null }, { null, null, null }, { null, null, null }, { null, null, null }, { null, null, null }, { null, null, null }, { null, null, null }, { null, null, null }, { null, null, null }, }, new String[] { "\u7528\u6236\u540D", "IP", "GUID" }) {
private static final long serialVersionUID = -6259343924352571655L;

public boolean isCellEditable(int row, int column) {
return false;
}
});
table.setBackground(new Color(255, 255, 255));
scrollPane.setViewportView(table);
table.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));

JScrollPane scrollPane_1 = new JScrollPane();
scrollPane_1.setBounds(12, 159, 370, 104);
getContentPane().add(scrollPane_1);

textArea = new JTextArea();
textArea.setLineWrap(true);
textArea.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if ((e.isControlDown() && e.getKeyCode() == KeyEvent.VK_ENTER) || (e.isAltDown() && e.getKeyCode() == KeyEvent.VK_S)) {
sendMessage();
}
}
});
scrollPane_1.setViewportView(textArea);

JButton button = new JButton("發送");
button.setBackground(SystemColor.control);
button.setBounds(141, 275, 83, 28);
button.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
sendMessage();
}
});
getContentPane().add(button);

JButton button_1 = new JButton("關閉");
button_1.setBackground(SystemColor.control);
button_1.setBounds(22, 275, 83, 28);
button_1.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
Msg.this.dispatchEvent(new WindowEvent(Msg.this, WindowEvent.WINDOW_CLOSING));
}
});
getContentPane().add(button_1);

JLabel lblNewLabel = new JLabel("當前在線人數");
lblNewLabel.setBounds(299, 29, 83, 18);
getContentPane().add(lblNewLabel);

lblNewLabel_1 = new JLabel("0");
lblNewLabel_1.setBounds(305, 59, 55, 18);
getContentPane().add(lblNewLabel_1);

JLabel lblNewLabel_2 = new JLabel("Alt+S或Ctrl+Enter發送");
lblNewLabel_2.setBounds(242, 280, 140, 18);
getContentPane().add(lblNewLabel_2);

this.setSize(400, 348);
setBackground(SystemColor.control);
setResizable(false);
setTitle("局域網聊天");
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
try {
sendBroadcast((guid + "2").getBytes(), broadcastAddress);
} catch (Exception e2) {
}
}
});

try {

uname = JOptionPane.showInputDialog("請輸入你的暱稱");
uname = uname == null ? "匿名" : uname;
server = new DatagramSocket(port);

broadcastAddress = InetAddress.getByName("255.255.255.255");

new AcceptBroadcastThread().start();// 啟動監聽
sendBroadcast((guid + "0" + uname).getBytes(), broadcastAddress);// 發送全網廣播,通知上線
} catch (Exception e) {
JOptionPane.showMessageDialog(this, "端口" + port + "被佔用!");
System.exit(0);
}
}

/**
* 向外發送數據
*
* @param data
* @param address
* @throws IOException
*/
public void sendBroadcast(byte[] data, InetAddress address) throws IOException {
DatagramPacket dp = new DatagramPacket(data, data.length, address, port);
server.send(dp);
}

/**
* 刷新列表
*/
public void refresh() {
// 清空列表
userTable.clear();
DefaultTableModel tableModel = ((DefaultTableModel) table.getModel());
for (int j = table.getRowCount(); j > 0; j--) {
tableModel.removeRow(j - 1);
}
try {
sendBroadcast((guid + "3" + uname).getBytes(), broadcastAddress);// 重新發送全網廣播,通知上線
} catch (Exception e) {
}
}

public void alertMessage(final String msg) {
new Thread() {
public void run() {
JOptionPane.showMessageDialog(Msg.this, msg);
};
}.start();
}

/**
* 發送文字消息
*/
public void sendMessage() {
int[] selectRows = table.getSelectedRows();
DefaultTableModel tableModel = (DefaultTableModel) table.getModel();
String msg = guid + "1" + textArea.getText();
byte[] data = string2Bytes(msg);
for (int i = 0, j = selectRows.length; i < j; i++) {
String key = (String) tableModel.getValueAt(selectRows[i], 2);
UserInfo ui = key == null ? null : userTable.get(key);
if (ui != null) {
try {
textArea.setText("");
sendBroadcast(data, ui.getIpAddress());
} catch (Exception e) {
JOptionPane.showMessageDialog(this, "發送消息到" + ui.getName() + "(" + ui.getIpAddress().getHostAddress() + ")失敗!", "發送失敗", JOptionPane.ERROR_MESSAGE);
}
}
}
}

private byte[] string2Bytes(String str) {
try {
return str.getBytes("UTF-8");
} catch (Exception e) {
}
return null;
}

class UserInfo {

private String guid;
private String name;
private InetAddress ipAddress;

public String getGuid() {
return guid;
}

public void setGuid(String guid) {
this.guid = guid;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public InetAddress getIpAddress() {
return ipAddress;
}

public void setIpAddress(InetAddress ipAddress) {
this.ipAddress = ipAddress;
}
}

class AcceptBroadcastThread extends Thread {
public void run() {
while (true) {
try {
DatagramPacket dp = new DatagramPacket(new byte[1024], 1024);
server.receive(dp);

String msg = new String(dp.getData(), 0, dp.getLength(), "UTF-8");// 解析廣播數據包
String uid = msg.substring(0, 32);
String type = msg.substring(32, 33);

if (type.equals("0") || type.equals("3")) {
UserInfo ui = new UserInfo();
ui.setGuid(uid);
ui.setName(msg.substring(33));
ui.setIpAddress(dp.getAddress());

// 刷新請求,只響應不做其他處理
if (userTable.containsKey(ui.getGuid()) && type.equals("3")) {
sendBroadcast((guid + "0" + uname).getBytes(), broadcastAddress);
}

// 上線通知
if (!userTable.containsKey(ui.getGuid())) {
userTable.put(ui.getGuid(), ui);// 將新用戶添加到用戶表
lblNewLabel_1.setText("" + userTable.size());

sendBroadcast((guid + "0" + uname).getBytes(), broadcastAddress);// 響應非本機廣播
((DefaultTableModel) table.getModel()).insertRow(0, new String[] { ui.getName(), ui.getIpAddress().getHostAddress(), ui.getGuid() });
}
} else if (type.equals("1")) {
UserInfo ui = userTable.get(uid);
alertMessage(ui.getName() + "(" + ui.getIpAddress().getHostAddress() + ")-" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "\r\n" + msg.substring(33));
} else {
userTable.remove(uid);// 移除用戶
lblNewLabel_1.setText("" + userTable.size());

DefaultTableModel tableModel = ((DefaultTableModel) table.getModel());
for (int i = 0, j = table.getRowCount(); i < j; i++) {
if (tableModel.getValueAt(i, 2).equals(uid)) {
tableModel.removeRow(i);
}
}
}
} catch (Exception e) {
}
}
}
}

public static void main(String[] args) throws Exception {
Msg msg = new Msg();
msg.setVisible(true);
}
}
...全文
853 54 打赏 收藏 转发到动态 举报
写回复
用AI写文章
54 条回复
切换为时间正序
请发表友善的回复…
发表回复
xeinstein 2012-05-11
  • 打赏
  • 举报
回复
我很努力的看下来了~~~结果晕了~~牛~!
hzw825 2011-11-02
  • 打赏
  • 举报
回复
问题已解决 感激不尽!
hzw825 2011-11-02
  • 打赏
  • 举报
回复
楼主 问个问题: 这种局域网聊天程序,是不是不要服务器端,但是每个客户端都要一个端口号?这样才能进行广播?
z740003446 2011-10-30
  • 打赏
  • 举报
回复
牛叉,编写Game撒
戴叔叔 2011-09-29
  • 打赏
  • 举报
回复
围观大牛
小恩yoo 2011-09-13
  • 打赏
  • 举报
回复
lz真的很棒啊、、学习、、、
lvliang123 2011-09-10
  • 打赏
  • 举报
回复
来学习下 谢谢楼主!
小绵羊 2011-09-10
  • 打赏
  • 举报
回复
  • 打赏
  • 举报
回复
dzr1990 2011-09-09
  • 打赏
  • 举报
回复
学习一个,楼主厉害……
小绵羊 2011-09-09
  • 打赏
  • 举报
回复
[Quote=引用 27 楼 kai27ks 的回复:]

楼主的代码里没怎么用布局管理器啊。好奇的问下你是用windowbulider开发的么
[/Quote]
不爱用布局管理器,用windowbulider调了下位置和尺寸
营营 2011-09-09
  • 打赏
  • 举报
回复
谢谢楼主~~~
woshixjj01 2011-09-09
  • 打赏
  • 举报
回复
参考下
Ade子夜 2011-09-09
  • 打赏
  • 举报
回复
2个小时?太有才了1
  • 打赏
  • 举报
回复
支持 开源分享...
kai27ks 2011-09-09
  • 打赏
  • 举报
回复
楼主的代码里没怎么用布局管理器啊。好奇的问下你是用windowbulider开发的么
小绵羊 2011-09-09
  • 打赏
  • 举报
回复
小绵羊 2011-09-09
  • 打赏
  • 举报
回复
今天来把代码重构一下
小绵羊 2011-09-09
  • 打赏
  • 举报
回复
。。悲剧的
小脩 2011-09-09
  • 打赏
  • 举报
回复
加载更多回复(34)

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧