Client段
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.swing.*;
public class ChatClient extends Thread implements ActionListener {
JFrame jframe = new JFrame("聊天室,客户端");
JTextArea jta = new JTextArea(10, 30);// 保存聊天信息
JList list = new JList();// 保存聊天用户列表
JTextField jtf1 = new JTextField("匿名", 10);
JLabel lab1 = new JLabel("昵称");
JTextField jtf2 = new JTextField(10);
JLabel lab2 = new JLabel("服务器");
JButton connBtn = new JButton("连接");
JLabel lab3 = new JLabel("消息");
JTextField jtf3 = new JTextField(20);// 聊天输入框
JButton sendBtn = new JButton("发送");
JCheckBox box = new JCheckBox("启动私聊");
PrintWriter pw;
BufferedReader br;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
DefaultListModel model = new DefaultListModel();
Hashtable<String, String> table = new Hashtable<String, String>();// 保存编号和呢称
public void paint() {
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
connBtn.addActionListener(this);
Container container = jframe.getContentPane();
JPanel northPanel = new JPanel();
northPanel.setBackground(Color.YELLOW);
northPanel.add(lab1);
northPanel.add(jtf1);
northPanel.add(lab2);
northPanel.add(jtf2);
northPanel.add(connBtn);
connBtn.setBackground(Color.YELLOW);
sendBtn.setBackground(Color.GREEN);
sendBtn.addActionListener(this);
box.setBackground(Color.GREEN);
JPanel southPanel = new JPanel();
southPanel.setBackground(Color.GREEN);
southPanel.add(box);
southPanel.add(lab3);
southPanel.add(jtf3);
southPanel.add(sendBtn);
JPanel westPanel = new JPanel(new BorderLayout());
JLabel userLab = new JLabel("成员列表");
westPanel.setBackground(Color.RED);
JScrollPane userPanel = new JScrollPane(list);
list.setBackground(Color.PINK);
westPanel.add(userLab, BorderLayout.NORTH);
westPanel.add(userPanel, BorderLayout.CENTER);
westPanel.setPreferredSize(new Dimension(100, 480));
JScrollPane centerPanel = new JScrollPane(jta);
jta.setBackground(Color.LIGHT_GRAY);
container.add(northPanel, BorderLayout.NORTH);
container.add(southPanel, BorderLayout.SOUTH);
container.add(westPanel, BorderLayout.WEST);
container.add(centerPanel, BorderLayout.CENTER);
list.setModel(model);
jframe.setSize(480, 480);
jframe.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
String name = e.getActionCommand();
if (name.equals("连接")) {
conn();
} else if (name.equals("发送")) {
printMessage();
}
}
public void conn() {
try {
Socket s = new Socket(jtf2.getText(), 1234);
connBtn.setEnabled(false);
pw = new PrintWriter(s.getOutputStream(), true);
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
this.start();// 启动接收聊天信息线程
} catch (UnknownHostException e) {
jta.append("连接服务器失败,请正确输入服务器地址\n");
} catch (IOException e) {
jta.append("连接服务器失败\n");
}
}
public void printMessage() {
if (pw != null) {
if (!box.isSelected()) {// 处理正常聊天信息
Date d = Calendar.getInstance().getTime();
String fmt = sdf.format(d);
pw
.println(fmt + " " + jtf1.getText() + "说 : "
+ jtf3.getText());
jtf3.setText("");
pw.flush();
} else {// 处理私聊信息
Date d = Calendar.getInstance().getTime();
User p = (User) list.getSelectedValue();// 得到私聊用户对象
if (p == null)
return;
String fmt = sdf.format(d);// ~代表是私聊的开始 p.getId()代表对谁进行私聊
pw.println("~" + p.getId() + "~" + "【私聊】" + fmt + " "
+ jtf1.getText() + "对你说 : " + jtf3.getText());
jta.append("【私聊】" + fmt + " " + "你对【" + p.getName() + "】说 : "
+ jtf3.getText() + "\n");
jtf3.setText("");
pw.flush();
}
}
}
public void run() {
pw.println("@" + jtf1.getText());
while (true) {
try {
String msg = br.readLine();
if (msg.startsWith("@")) {// 得到的是用户登陆信息
String userList[] = msg.split("@");
table.put(userList[2], userList[1]);// 保存得到的用户编号和呢称
User p = new User();// 以此编号和呢称创建一个用户
p.setId(userList[2]);
p.setName(userList[1]);
model.addElement(p);// 将用户显示在列表中
list.setModel(model);
} else if (msg.startsWith("#")) {// 得到的是用户退出信息
String userList[] = msg.split("#");
String id = userList[1];
User p = new User();
p.setId(id);// 通过编号创建一个User对象
model.removeElement(p);// 删除列表中与此编号相同的用户
list.setModel(model);// 从新显示列表
} else
jta.append(msg + "\n");// 正常聊天信息
} catch (IOException e) {
jta.append("与服务器断开连接\n");
break;
}
}
}
public static void main(String[] args) {
new ChatClient().paint();
}
}
Sever段
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.swing.*;
public class ChatServer implements ActionListener {
private JFrame jframe = new JFrame("聊天室,服务器");
JTextArea jta = new JTextArea(10, 20);
JTextField jtf = new JTextField(20);
OutputStream os = null;
PrintWriter pw = null;
Vector<Socket> v = new Vector<Socket>();//保存所有客户端
Hashtable<String, String> table = new Hashtable<String, String>();//保存用户编号和呢称
Hashtable<Socket, String> socketTable = new Hashtable<Socket, String>();//保存客户端和用户编号
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
public void paint() {
Container container = jframe.getContentPane();
JPanel northPanel = new JPanel();
JLabel lab1 = new JLabel("系统消息");
JButton btn = new JButton("发送");
btn.addActionListener(this);
northPanel.add(lab1);
northPanel.add(jtf);
northPanel.add(btn);
JScrollPane context = new JScrollPane(jta);
container.add(northPanel, BorderLayout.NORTH);
container.add(context);
jframe.setSize(480, 400);
jframe.setVisible(true);
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
createServer();
}
public void createServer() {
try {
ServerSocket ss = new ServerSocket(1234);//创建服务器
jta.append("服务器已经启动\n");
while (true) {
Socket s = ss.accept();//等待客户端连接
os = s.getOutputStream();
pw = new PrintWriter(os, true);
new Service(s);//启动与客户端交互的线程
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void actionPerformed(ActionEvent e) {
writeMessage();//发送系统消息
}
public void writeMessage() {//发送系统消息
Date d = Calendar.getInstance().getTime();
String fmt = sdf.format(d);
int size = v.size();// v保存的是所有的客户端
for (int i = 0; i < size; i++) {
Socket sk = v.get(i);
try {
PrintWriter pw = new PrintWriter(sk.getOutputStream(), true);
pw.println(fmt + " 系统消息 : " + jtf.getText());
} catch (IOException e) {
continue;
}
}
jtf.setText("");
}
private class Service extends Thread {
InputStream is = null;
InputStreamReader isr = null;
BufferedReader br = null;
Socket s;
public Service(Socket s) {
try {
this.s = s;
is = s.getInputStream();
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
} catch (Exception e) {
e.printStackTrace();
}
this.start();//启动交互线程
}
public void run() {
while (true) {
try {
String msg = br.readLine();//读取客户端发送的消息
sendAll(s, msg);//处理发送的消息
} catch (IOException e) {
v.remove(s);
String id = socketTable.remove(s);
String name = table.remove(id);
jta.append("【" + name + "】" + "离开聊天室...");
jta.append("服务器现在人数为: " + v.size() + "人\n");
sendAll(s, "#" + id);//处理用户退出消息
break;
}
}
}
synchronized public void sendAll(Socket s, String msg) {
if (msg.startsWith("@")) {//处理用户登陆消息
String id = System.currentTimeMillis() + "";
msg = msg + "@" + id;
String str[] = msg.split("@");
table.put(id, str[1]);//保存编号和对应的呢称
socketTable.put(s, id);//保存客户端和对应的编号
v.add(s);//保存客户端
jta.append("【" + str[1] + "】" + "进入聊天室...");
jta.append("服务器现在人数为: " + v.size() + "人\n");
try {
PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
Set<String> set = table.keySet();
Iterator<String> it = set.iterator();
while (it.hasNext()) {
String clientID = it.next();
pw.println("@" + table.get(clientID) + "@" + clientID);//将登陆消息发给自己
}
} catch (IOException e) {
e.printStackTrace();
}
for (int i = 0; i < v.size() - 1; i++) {//将登陆消息发给以前登陆的客户端
Socket sk = v.get(i);
try {
PrintWriter pw = new PrintWriter(sk.getOutputStream(),
true);
pw.println(msg);
} catch (IOException e) {
continue;
}
}
} else if (msg.startsWith("~")) {//处理私聊信息
String privateMsg[] = new String[2];
privateMsg[0] = msg.substring(1, msg.indexOf("~", 1));
privateMsg[1] = msg.substring(msg.indexOf("~", 1)+1, msg.length());
String toID = privateMsg[0];//保存的是用户的编号
Set<Socket> coll = socketTable.keySet();
Iterator<Socket> it = coll.iterator();
while (it.hasNext()) {
Socket id = it.next();
if (socketTable.get(id).equals(toID)) {//通过客户端找用户的编号
try {
PrintWriter pw = new PrintWriter(id
.getOutputStream(), true);
pw.println(privateMsg[1]);//如果编号相同则发给此客户端
} catch (IOException e) {
e.printStackTrace();
}
}
}
} else {
for (int i = 0; i < v.size(); i++) {//处理正常的聊天消息
Socket sk = v.get(i);
try {
PrintWriter pw = new PrintWriter(sk.getOutputStream(),
true);
pw.println(msg);
} catch (IOException e) {
continue;
}
}
}
}
}
public static void main(String[] args) {
new ChatServer().paint();
}
}
用来创建用户名称和id
public class User {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int hashCode() {
return id.hashCode();
}
public boolean equals(Object obj) {
if (obj == null)
return false;
if (!(obj instanceof User))
return false;
User user = (User) obj;
return this.id.equals(user.id);
}
public String toString() {
return this.name;
}
}