功能:
登录
若用户账号不存在,弹出错误
若用户密码错误,弹出错误
若用户账号已在线,弹出错误
注册
若用户已注册,弹出错误
聊天室
多人聊天,类似QQ里的群。
点击右侧的在线用户,可进行一对一聊天。
一对一聊天
在聊天室中点击在线用户可进入此窗口。
发送消息后,对方会收到消息,并弹出一对一聊天窗口 。
说明:
服务端的IP和端口固定。(代码中使用127.0.0.1作为服务端的IP)
客户端通过该IP和端口访问服务器。
客户端向服务器发送消息,服务器根据消息做出不同的处理,并可能向其他客户端发送消息。
每个客户端都有一个客户端server进程,以接收服务端发来的消息。
初始化客户端时,启动客户端server进程,监听任意一个可用端口。用户登录时,将本地账户、密码、本地的server进程端口发给服务端,服务端检验用户合法性,若合 法,则更新该账户的IP地址和端口。以后服务端即可向该IP发送消息。
代码:
项目工程结构:
Server
package chatroomutil; import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket; public abstract class Server {
protected ServerSocket sSocket;
public Server() {
}
protected int listen() {
while (true) {
Socket ots = null;
try {
ots = sSocket.accept();
} catch (IOException e) {
ChatRoomUtil.showErrorBox("服务器Accept错误");
System.exit(-1);
}
Thread hThread = new Thread(new handleThread(ots));
hThread.start();
}
}
// 处理消息的进程 的内部类
class handleThread implements Runnable {
Socket ots;
handleThread(Socket ots) {
this.ots = ots;
}
@Override
public void run() {
handleMessage(ots);
}
};
protected abstract String handle(Socket ots,String rMessage);//处理函数,输入收到的消息,返回要发送的消息
private String handleMessage(Socket ots) {
StringBuffer buffer=new StringBuffer();
BufferedReader reader=ChatRoomUtil.getMsgFromSocket(ots,buffer);//获取消息
String rMessage = buffer.toString();
String message=handle(ots,rMessage);//处理消息
PrintWriter writer=ChatRoomUtil.putMesgToSocket(ots, message);//发送消息
ChatRoomUtil.closeSocket(ots,reader,writer);//关闭
return null;
}
}
ChatRoomUtil
package chatroomutil;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import javax.swing.JOptionPane; public class ChatRoomUtil {
public static String showErrorBox(String message) {//显示错误信息对话框
JOptionPane.showMessageDialog(null, message, "错误",
JOptionPane.ERROR_MESSAGE);
return message;
}
//获取消息
public static BufferedReader getMsgFromSocket(Socket socket,StringBuffer buffer){
BufferedReader reader = null;
try {
reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
ChatRoomUtil.showErrorBox("获取Socket输入流错误");
System.exit(-1);
}
try {
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
buffer.deleteCharAt(buffer.length()-1);//去掉最后一个回车符
} catch (IOException e) {
ChatRoomUtil.showErrorBox("读取Socket输入流错误");
System.exit(-1);
}
try {
socket.shutdownInput();
} catch (IOException e) {
ChatRoomUtil.showErrorBox("关闭Socket输入时发生错误");
System.exit(-1);
}
return reader;
}
//发送消息
public static PrintWriter putMesgToSocket(Socket socket,String message){
PrintWriter writer = null;
try {
writer = new PrintWriter(socket.getOutputStream());
} catch (IOException e) {
ChatRoomUtil.showErrorBox("获取Socket输出流错误");
System.exit(-1);
}
writer.println(message);
writer.flush();
try {
socket.shutdownOutput();
} catch (IOException e1) {
ChatRoomUtil.showErrorBox("关闭Socket输出时发生错误");
System.exit(-1);
}
return writer;
}
//关闭socket、输入流、输出流
public static void closeSocket(Socket socket,BufferedReader reader,PrintWriter writer ){
try {
reader.close();
} catch (IOException e) {
ChatRoomUtil.showErrorBox("关闭Scoket输入流时发生错误");
System.exit(-1);
}
writer.close();
try {
socket.close();
} catch (IOException e) {
ChatRoomUtil.showErrorBox("关闭Scoket输出流时发生错误");
System.exit(-1);
}
}
}
ServerServer
package chatroomserver;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Enumeration;
import java.util.Hashtable;
import chatroomsend.Send;
import chatroomutil.ChatRoomUtil;
import chatroomutil.Server; public class ServerServer extends Server {
Hashtable<String, User> onlineTable = new Hashtable<String, User>();// 在线用户集合
Hashtable<String, User> offlineTable = new Hashtable<String, User>();// 离线用户集合
// 用户内部类
class User {
String id;
String pwd;
String IP;
int port;
User(String id, String pwd) {
this.id = id;
this.pwd = pwd;
}
}
// 发送进程内部类
class sendThread implements Runnable {
String mesg;
String IP;
int port;
sendThread(String IP, int port, String mesg) {
this.IP = IP;
this.port = port;
this.mesg = mesg;
}
@Override
public void run() {
Send sendClient = new Send();
sendClient.connect(IP, port, 1000);
sendClient.send(mesg);
}
};
public ServerServer(int port) throws IOException {
init(port);
initUsers();
listen();
}
private int init(int port) throws IOException {
try {
sSocket = new ServerSocket(port);//绑定指定端口
} catch (IOException e) {
ChatRoomUtil.showErrorBox("服务器初始化失败,无法绑定端口。");
System.exit(-1);
}
return port;
}
private int initUsers() {//读取Users文件,初始化offlineTable
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("Users.txt"));
} catch (FileNotFoundException e1) {
ChatRoomUtil.showErrorBox("无法找到User文件");
System.exit(-1);
}
String line;
String[] fa;
try {
while ((line = reader.readLine()) != null) {
fa = line.split(":", 2);
User f = new User(fa[0], fa[1]);
offlineTable.put(fa[0], f);
}
reader.close();
} catch (IOException e) {
ChatRoomUtil.showErrorBox("读取User文件错误");
System.exit(-1);
}
return 0;
}
private int saveNewUser(String id, String pwd) {//将新用户写入Users文件最后
try {
RandomAccessFile file = new RandomAccessFile("Users.txt", "rw");
file.seek(file.length());
file.writeBytes(id + ":" + pwd + "\r\n");
file.close();
} catch (FileNotFoundException e) {
ChatRoomUtil.showErrorBox("写入User文件错误");
System.exit(-1);
} catch (IOException e) {
ChatRoomUtil.showErrorBox("写入User文件错误");
System.exit(-1);
}
return 0;
}
String loginCheck(String id, String pwd, String IP, int port) {//检查登录用户的合法性
System.out.println("logi check");
if (onlineTable.containsKey(id))
return "alreadyonline";//该用户已在线
User f = offlineTable.get(id);
if (f == null)
return "nothisid";//无此用户
if (f.pwd.compareTo(pwd) == 0) {
oneUserOnline(id, IP, port);
sendOnlinesToNewOnlineUser(id, IP, port);
sendNewOnlineUserToOnlines(id);
return "yes";//合法
} else {
return "wrong";//密码错误
}
}
int oneUserOnline(String id, String IP, int port) {//一个新用户上线
User f = offlineTable.get(id);
offlineTable.remove(id);
onlineTable.put(id, f);
f.IP = IP;
f.port = port;
return 0;
}
int sendNewOnlineUserToOnlines(String id) {//给所有在线用户发送新上线的用户的id
Enumeration<User> fs = onlineTable.elements();
while (fs.hasMoreElements()) {
User f = fs.nextElement();
if (f.id.compareTo(id) != 0) {
Thread hThread = new Thread(
new sendThread(f.IP, f.port, "newf" + id));
hThread.start();
}
}
return 0;
}
int sendMesg(String mesg) {//向所有在线用户转发一条消息
Enumeration<User> fs = onlineTable.elements();
while (fs.hasMoreElements()) {
User f = fs.nextElement();
Thread hThread = new Thread(
new sendThread(f.IP, f.port, "mesg" + mesg));
hThread.start();
}
return 0;
}
int sendChat(String id, String mesg) {//向一个用户发送一条一对一聊天的消息
User f = onlineTable.get(id);
Thread hThread = new Thread(
new sendThread(f.IP, f.port, "chat" + mesg));
hThread.start();
return 0;
}
String newRegisUser(String id, String pwd) {//有新注册的用户
if (onlineTable.containsKey(id) || offlineTable.containsKey(id)) {
return "no";
}
offlineTable.put(id, new User(id, pwd));
saveNewUser(id, pwd);
return "yes";
}
int sendOnlinesToNewOnlineUser(String id, String IP, int port) {//给新上线的用户发送所有已在线用户的id
if (onlineTable.isEmpty() || onlineTable.size() == 1) {
return 0;
}
StringBuffer strBuf = new StringBuffer();
Enumeration<User> fs = onlineTable.elements();
while (fs.hasMoreElements()) {
User f = fs.nextElement();
if (f.id.compareTo(id) != 0) {
strBuf.append(f.id);
strBuf.append(";");
}
}
String str = strBuf.toString();
Thread hThread = new Thread(new sendThread(IP, port, "newf" + str));
hThread.start();
return 0;
}
int oneUserOffline(String id) {//有一个用户下线,将其下线消息发送给所有在线用户
Enumeration<User> fs = onlineTable.elements();
while (fs.hasMoreElements()) {
User f = fs.nextElement();
if (f.id.compareTo(id) == 0) {
onlineTable.remove(id);
offlineTable.put(id, f);
} else {
Thread hThread = new Thread(
new sendThread(f.IP, f.port, "offl" + id));
hThread.start();
}
}
return 0;
}
protected String handle(Socket ots,String rMessage){
System.out.println("handle");
if (rMessage.startsWith("regi")) {//注册
rMessage = rMessage.substring("regi".length());
String id = rMessage.substring(0, rMessage.indexOf(','));
String pwd = rMessage.substring(rMessage.indexOf(',') + 1);
return newRegisUser(id, pwd);
}
if (rMessage.startsWith("logi")) {//登录
System.out.println("logi");
rMessage = rMessage.substring("logi".length());
String id = rMessage.substring(0, rMessage.indexOf(','));
String pwd = rMessage.substring(rMessage.indexOf(',') + 1,
rMessage.lastIndexOf(','));
String portstr = rMessage.substring(rMessage.lastIndexOf(',') + 1);
int port = new Integer(portstr);
String IP = ots.getInetAddress().getHostAddress();
return loginCheck(id, pwd, IP, port);
}
if (rMessage.startsWith("mesg")) {//聊天室消息
String mesg = rMessage.substring(("mesg").length());
sendMesg(mesg);
return "getm";
}
if (rMessage.startsWith("chat")) {//一对一消息
String chat = rMessage.substring(("chat").length());
String id = chat.substring(0, chat.indexOf(':'));
String mesg = chat.substring(chat.indexOf(':') + 1);
sendChat(id, mesg);
return "getm";
}
if (rMessage.startsWith("offl")) {//下线
String id = rMessage.substring(("offl").length());
oneUserOffline(id);
return "getm";
}
return "getm";
} public static void main(String[] args) {
try {
new ServerServer(65142);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Send
package chatroomsend;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import chatroomutil.ChatRoomUtil; public class Send {
Socket socket;
public Send() {
super();
socket = new Socket();
}
public int connect(String IP, int port, int timeout) {//连接
try {
socket.connect(new InetSocketAddress(IP, port), timeout);
} catch (IOException e) {
return -1;
}
return 0;
}
public String send(String message) {
PrintWriter writer=ChatRoomUtil.putMesgToSocket(socket, message);
StringBuffer buffer=new StringBuffer();
BufferedReader reader=ChatRoomUtil.getMsgFromSocket(socket,buffer);
String rMessage = buffer.toString();
ChatRoomUtil.closeSocket(socket,reader,writer);
return rMessage;
}
}
LoginBox
package chatroomclient;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import javax.swing.*;
import chatroomsend.Send;
import chatroomutil.ChatRoomUtil; public class LoginBox extends JFrame implements ActionListener, MouseListener {
private static final long serialVersionUID = -329711894663212488L;
ClientServer myServer;
String serverIP;
int serverPort;
JLabel l_account = new JLabel();
JLabel l_password = new JLabel();
JLabel l_regist = new JLabel();
JTextField j_account = new JTextField();
JPasswordField j_password = new JPasswordField();
JButton submit = new JButton();
JButton cancel = new JButton();
JLabel clearAccount = new JLabel();
JLabel clearPassword = new JLabel();
public LoginBox(String ip, int port) {
super("登录");
try {
myServer = new ClientServer(serverIP, serverPort);
Thread myServerThread = new Thread(myServer);
myServerThread.start();
} catch (IOException e) {
ChatRoomUtil.showErrorBox("服务器进程初始化失败,无法绑定端口。");
System.exit(-1);
}
serverIP = ip;
serverPort = port;
setLayout(null);
l_account.setVisible(true);
l_account.setBounds(80, 40, 50, 30);
l_account.setText("账号:");
l_password.setVisible(true);
l_password.setBounds(80, 80, 50, 30);
l_password.setText("密码:");
j_account.setBounds(130, 40, 150, 30);
j_password.setBounds(130, 80, 150, 30);
clearAccount.setBounds(280, 42, 26, 26);
clearPassword.setBounds(280, 82, 26, 26);
submit.setBounds(100, 130, 80, 30);
submit.setText("登录");
cancel.setText("取消");
clearAccount.setText("X");
clearPassword.setText("X");
clearAccount.setOpaque(true);
clearPassword.setOpaque(true);
clearAccount.setBackground(Color.LIGHT_GRAY);
clearPassword.setBackground(Color.LIGHT_GRAY);
clearAccount.setHorizontalAlignment(JLabel.CENTER);
clearPassword.setHorizontalAlignment(JLabel.CENTER);
submit.setBackground(Color.LIGHT_GRAY);
cancel.setBackground(Color.LIGHT_GRAY);
submit.addActionListener(this);
cancel.addActionListener(this);
cancel.setBounds(190, 130, 80, 30);
l_regist.setBounds(270, 200, 70, 30);
l_regist.setText("没有账号?");
this.add(l_account);
this.add(l_password);
this.add(j_account);
this.add(j_password);
this.add(submit);
this.add(cancel);
this.add(l_regist);
this.add(clearAccount);
this.add(clearPassword);
setBounds(480, 240, 370, 270);
setVisible(true);
setResizable(false);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
validate();
l_regist.addMouseListener(this);
clearAccount.addMouseListener(this);
clearPassword.addMouseListener(this);
}
String checkPwd(String id, String pwd) {
Send sendClient = new Send();
sendClient.connect(serverIP, serverPort, 1000);
String ret= sendClient
.send("logi" + id + "," + pwd + "," + myServer.getMyServerPort());
if (ret.compareTo("yes") == 0) {
myServer.chatRoom = new ChatRoom(id, serverIP, serverPort);
dispose();
} else if (ret.compareTo("wrong") == 0) {
ChatRoomUtil.showErrorBox("登录失败,密码有误。");
} else if (ret.compareTo("alreadyonline") == 0) {
ChatRoomUtil.showErrorBox("登录失败,该账号已在线");
} else if (ret.compareTo("nothisid") == 0) {
ChatRoomUtil.showErrorBox("登录失败,账号不存在。");
new RegisBox(serverIP, serverPort,
myServer.getMyServerPort());
}
return ret;
}
@Override
public void actionPerformed(ActionEvent e) {
Object t = e.getSource();
if (e.getSource().getClass() == JButton.class) {
JButton button = (JButton) (t);
if (button.getText().compareTo("登录") == 0) {
String id = j_account.getText();
String pwd = String.valueOf(j_password.getPassword());
if (id.compareTo("") == 0 || pwd.compareTo("") == 0) {
ChatRoomUtil.showErrorBox("账号与密码均不能为空");
return;
}
checkPwd(id, pwd);
}
if (button.getText().compareTo("取消") == 0) {
dispose();
System.exit(0);
}
}
}
@Override
public void mouseClicked(MouseEvent e) {
if (e.getSource().equals(l_regist)) {
new RegisBox(serverIP, serverPort,
myServer.getMyServerPort());
}
if (e.getSource().equals(clearAccount)) {
j_account.setText("");
}
if (e.getSource().equals(clearPassword)) {
j_password.setText("");
}
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
} @Override
public void mouseEntered(MouseEvent e) {
Object x = e.getSource();
if (x.equals(l_regist)) {
JLabel l = (JLabel) x;
l.setForeground(Color.blue);
}
if (x.equals(clearAccount) || x.equals(clearPassword)) {
JLabel l = (JLabel) x;
l.setBackground(Color.GRAY);
}
} @Override
public void mouseExited(MouseEvent e) {
Object x = e.getSource();
if (x.equals(l_regist)) {
JLabel l = (JLabel) x;
l.setForeground(Color.BLACK);
}
if (x.equals(clearAccount) || x.equals(clearPassword)) {
JLabel l = (JLabel) x;
l.setBackground(Color.LIGHT_GRAY);
}
}
public static void main(String[] args) {
String serverIP = "127.0.0.1";
int serverPort = 65142;
new LoginBox(serverIP, serverPort);
}
}
RegisBox
package chatroomclient;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import chatroomsend.Send;
import chatroomutil.ChatRoomUtil;
public class RegisBox extends JFrame implements ActionListener {
private static final long serialVersionUID = 5795626909275119718L;
String serverIP;
int serverPort;
int myServerPort;
JLabel id_label = new JLabel();
JLabel pwd_label = new JLabel();
JLabel pwdCheck_label = new JLabel();
JLabel num_label = new JLabel();
JLabel firstName_label = new JLabel();
JLabel lastName_label = new JLabel();
JLabel age_label = new JLabel();
JLabel sex_label = new JLabel();
JTextField id_text = new JTextField();
JPasswordField pwd_text = new JPasswordField();
JPasswordField pwdCheck_text = new JPasswordField();
JTextField num_text = new JTextField();
JTextField firstName_text = new JTextField();
JTextField lastName_text = new JTextField();
JTextField age_text = new JTextField();
JComboBox sex_box = new JComboBox();
JButton cancel = new JButton();
JButton regis = new JButton();
public RegisBox(String serverIP, int serverPort, int myServerPort) {
super();
this.serverIP = serverIP;
this.serverPort = serverPort;
this.myServerPort = myServerPort;
setLayout(null);
setTitle("注册");
id_label.setBounds(60, 23, 50, 20);
pwd_label.setBounds(60, 53, 50, 20);
pwdCheck_label.setBounds(50, 83, 70, 20);
num_label.setBounds(60, 113, 50, 20);
firstName_label.setBounds(60, 143, 50, 20);
lastName_label.setBounds(60, 173, 50, 20);
age_label.setBounds(60, 203, 50, 20);
sex_label.setBounds(60, 233, 50, 20);
id_text.setBounds(130, 20, 200, 26);
pwd_text.setBounds(130, 50, 200, 26);
pwdCheck_text.setBounds(130, 80, 200, 26);
num_text.setBounds(130, 110, 200, 26);
firstName_text.setBounds(130, 140, 200, 26);
lastName_text.setBounds(130, 170, 200, 26);
age_text.setBounds(130, 200, 200, 26);
sex_box.setBounds(130, 230, 200, 26);
regis.setBounds(190, 270, 70, 30);
cancel.setBounds(270, 270, 70, 30);
id_label.setText("账号");
pwd_label.setText("密码");
pwdCheck_label.setText("密码确认");
num_label.setText("编号");
firstName_label.setText("名");
lastName_label.setText("姓");
age_label.setText("年龄");
sex_label.setText("性别");
sex_box.addItem("男");
sex_box.addItem("女");
regis.setText("提交");
cancel.setText("取消");
regis.setBackground(Color.LIGHT_GRAY);
cancel.setBackground(Color.LIGHT_GRAY);
sex_box.setBackground(Color.LIGHT_GRAY);
regis.addActionListener(this);
cancel.addActionListener(this);
this.add(id_label);
this.add(pwd_label);
this.add(pwdCheck_label);
this.add(num_label);
this.add(firstName_label);
this.add(lastName_label);
this.add(age_label);
this.add(sex_label);
this.add(id_text);
this.add(pwd_text);
this.add(pwdCheck_text);
this.add(num_text);
this.add(firstName_text);
this.add(lastName_text);
this.add(age_text);
this.add(sex_box);
this.add(regis);
this.add(cancel);
setBounds(200, 200, 500, 400);
validate();
setResizable(false);
setVisible(true);
}
boolean regis(String serverIP, int serverPort, String id, String pwd,
int myServerPort) {
Send sendClient = new Send();
sendClient.connect(serverIP, serverPort, 1000);
if (sendClient.send("regi" + id + "," + pwd).compareTo("yes") == 0) {
return true;
}
return false;
}
boolean check() {
String id = id_text.getText();
String pwd = String.valueOf(pwd_text.getPassword());
String pwdc = String.valueOf(pwdCheck_text.getPassword());
String fName = firstName_text.getText();
String lName = lastName_text.getText();
String age = age_text.getText();
String num = num_text.getText();
String sex = sex_box.getSelectedItem().toString();
if (id.compareTo("") == 0) {
ChatRoomUtil.showErrorBox("账号不能为空");
return false;
}
if (pwd.compareTo("") == 0) {
ChatRoomUtil.showErrorBox("密码不能为空");
return false;
}
if (pwdc.compareTo("") == 0) {
ChatRoomUtil.showErrorBox("请确认密码");
return false;
}
if (pwd.compareTo(pwdc) != 0) {
ChatRoomUtil.showErrorBox("两次输入的密码不符");
return false;
}
if (num.compareTo("") == 0) {
ChatRoomUtil.showErrorBox("编号不能为空");
return false;
}
if (fName.compareTo("") == 0) {
ChatRoomUtil.showErrorBox("名不能为空");
return false;
}
if (lName.compareTo("") == 0) {
ChatRoomUtil.showErrorBox("姓不能为空");
return false;
}
if (age.compareTo("") == 0) {
ChatRoomUtil.showErrorBox("年龄不能为空");
return false;
}
if (sex.compareTo("") == 0) {
ChatRoomUtil.showErrorBox("性别不能为空");
return false;
}
if (regis(serverIP, serverPort, id, pwd, myServerPort)) {
dispose();
} else {
ChatRoomUtil.showErrorBox("注册失败。该用户已存在");
return false;
}
return true;
}
@Override
public void actionPerformed(ActionEvent e) {
Object t = e.getSource();
if (e.getSource().getClass() == JButton.class) {
JButton button = (JButton) (t);
if (button.getText().compareTo("提交") == 0) {
check();
}
if (button.getText().compareTo("取消") == 0) {
dispose();
}
}
}
}
ClientServer
package chatroomclient;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import chatroomutil.ChatRoomUtil;
import chatroomutil.Server; public class ClientServer extends Server implements Runnable {
ChatRoom chatRoom;
private int myPort;
public ClientServer(String serverIP, int serverPort) throws IOException {
super();
myPort = init();
}
int getMyServerPort() {
return myPort;
}
private int createServerSocket(int i) throws IOException {//绑定端口i
if (i >= 65536) {
ChatRoomUtil.showErrorBox("ClientServer无端口可绑定");
System.exit(-1);
}
try {
sSocket = new ServerSocket(i);
} catch (IOException e) {
return createServerSocket(i + 1);
}
return i;
}
private int init() throws IOException {
int port = createServerSocket(1025);
return port;
}
@Override
protected String handle(Socket ots,String rMessage){
String message = "getm";
if (rMessage.startsWith("newf")) {
while (chatRoom == null) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
ChatRoomUtil.showErrorBox("ClientServer在Sleep时出错");
System.exit(-1);
}
}
String ids = rMessage.substring(("newf").length());
String[] idArray = ids.split(";");
chatRoom.addFriend(idArray);
}
if (rMessage.startsWith("offl")) {
String name = rMessage.substring(("offl").length());
chatRoom.removeFriend(name);
}
if (rMessage.startsWith("mesg")) {
String mesg = rMessage.substring(("mesg").length());
chatRoom.addRecord(mesg);
}
if (rMessage.startsWith("chat")) {
String chat = rMessage.substring(("chat").length());
String id = chat.substring(0, chat.indexOf(':'));
String mesg = chat.substring(chat.indexOf(':') + 1);
chatRoom.dialogAddRecord(id, mesg);
}
return message;
}
@Override
public void run() {
listen();
}
}
ChatRoom
package chatroomclient;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.TimerTask;
import javax.swing.*;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import chatroomsend.Send;
import chatroomutil.ChatRoomUtil; public class ChatRoom extends JFrame implements ActionListener, MouseListener {
private static final long serialVersionUID = -9016166784223701159L;
String myId;
String serverIP;
int serverPort;
JLabel chatRoomLabel = new JLabel();
JLabel onlineLabel = new JLabel();
JTextArea chatArea = new JTextArea();
JPanel onlineArea = new JPanel();
JTextArea sendArea = new JTextArea(5, 20);
JButton sendButton = new JButton();
JScrollPane chatScroll = new JScrollPane(chatArea);
JScrollPane onlineScroll = new JScrollPane(onlineArea);
JScrollPane sendScroll = new JScrollPane(sendArea);
JPanel chatPanel = new JPanel();
JPanel onlinePanel = new JPanel();
JPanel sendPanel = new JPanel();
JPanel chatAndOnlinePanel = new JPanel();
HashSet<String> friends = new HashSet<String>();
Hashtable<String, ChatDialog> chatDialogs = new Hashtable<String, ChatDialog>();
BorderLayout mainLayout = new BorderLayout();
BorderLayout chatLayout = new BorderLayout();
BorderLayout onlineLayout = new BorderLayout();
BorderLayout sendLayout = new BorderLayout();
BorderLayout chatAndOnlineLayout = new BorderLayout();
FlowLayout onlineAreaLayout = new FlowLayout();
public ChatRoom(String id, String serverIP, int port) {
super("聊天室 " + id);
this.myId = id;
this.serverIP = serverIP;
this.serverPort = port;
mainLayout.setVgap(5);
sendLayout.setHgap(10);
chatAndOnlineLayout.setHgap(15);
onlineAreaLayout.setVgap(1);
this.setLayout(mainLayout);
chatPanel.setLayout(chatLayout);
onlinePanel.setLayout(onlineLayout);
sendPanel.setLayout(sendLayout);
chatAndOnlinePanel.setLayout(chatAndOnlineLayout);
chatArea.setLineWrap(true);
sendArea.setLineWrap(true);
onlineArea.setLayout(onlineAreaLayout);
onlineArea.setPreferredSize(new Dimension(130, 200));
sendButton.setText(" 发送 ");
sendButton.setBackground(Color.LIGHT_GRAY);
sendButton.addActionListener(this);
onlineLabel.setText("在线好友(点击可开始聊天)");
chatRoomLabel.setText("聊天");
chatArea.setEditable(false);
chatArea.setBackground(new Color(230, 230, 230));
chatPanel.add(chatRoomLabel, BorderLayout.NORTH);
chatPanel.add(chatScroll, BorderLayout.CENTER);
onlinePanel.add(onlineLabel, BorderLayout.NORTH);
onlinePanel.add(onlineScroll, BorderLayout.CENTER);
sendPanel.add(sendScroll, BorderLayout.CENTER);
sendPanel.add(sendButton, BorderLayout.EAST);
chatAndOnlinePanel.add(chatPanel, BorderLayout.CENTER);
chatAndOnlinePanel.add(onlinePanel, BorderLayout.EAST);
this.add(sendPanel, BorderLayout.SOUTH);
this.add(chatAndOnlinePanel, BorderLayout.CENTER);
friends.add(myId);
this.setBounds(200, 200, 600, 650);
setVisible(true);
reFreshOnlineArea();
this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {//点击关闭按钮时发送下线消息
sendOffLine();
System.exit(0);
}
});
sendArea.addCaretListener(new CaretListener() {
@Override
public void caretUpdate(CaretEvent e) {
String str = sendArea.getText();
if (str.length() > 5000) {
ChatRoomUtil.showErrorBox("字数过多,超出限制。");
}
}
});
new java.util.Timer().schedule(new TimerTask() {//定时刷新界面
public void run() {
repaint();
}
}, 400, 400);
}
int reFreshOnlineArea() {//刷新当前在线用户
int size = friends.size();
onlineArea.removeAll();
Iterator<String> it = friends.iterator();
while (it.hasNext()) {
String str = it.next();
String id = str;
JLabel label = new JLabel(id);
label.addMouseListener(this);
label.setPreferredSize(new Dimension(130, 20));
label.setBackground(Color.GRAY);
label.setForeground(Color.WHITE);
label.setHorizontalAlignment(JLabel.CENTER);
label.setOpaque(true);
onlineArea.add(label);
}
onlineArea.setPreferredSize(new Dimension(130, size * 22));
this.repaint();
this.validate();
return 0;
}
int sendOffLine() {//发送下线消息
Send sendClient = new Send();
sendClient.connect(serverIP, serverPort, 1000);
sendClient.send("offl" + myId);
return 0;
}
public int addFriend(String[] fs) {//添加上线的用户
for (int i = 0; i < fs.length; i++) {
friends.add(fs[i]);
}
reFreshOnlineArea();
return 0;
}
public int removeFriend(String friendID) {//移除一个用户(已下线)
friends.remove(friendID);
reFreshOnlineArea();
return 0;
}
public int addRecord(String mesg) {//添加聊天记录
chatArea.append(mesg + "\n");
chatArea.setCaretPosition(chatArea.getText().length());
this.validate();
return 0;
}
public int dialogAddRecord(String id, String mesg) {//给一对一聊天增加聊天记录
if (chatDialogs.containsKey(id) == false) {
chatDialogs.put(id,
new ChatDialog(this, myId, id, serverIP, serverPort));
}
chatDialogs.get(id).addRecord(mesg);
return 0;
}
int removeDialog(String id) {//移除一对一聊天
chatDialogs.remove(id);
return 0;
}
private String sendMessage(String mesg) {//发送群聊消息
Send sendClient = new Send();
sendClient.connect(serverIP, serverPort, 1000);
String getm = sendClient.send("mesg" + myId + ": \n" + mesg);
return getm;
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource().getClass() == JButton.class) {
sendMessage(sendArea.getText());
sendArea.setText("");
}
}
@Override
public void mouseClicked(MouseEvent e) {
if (e.getSource().getClass() == JLabel.class) {
JLabel l = (JLabel) e.getSource();
if (l.getText().compareTo(myId) == 0) {
return;
}
if (chatDialogs.containsKey(l.getText())) {
return;
}
chatDialogs.put(l.getText(), new ChatDialog(this, myId, l.getText(),
serverIP, serverPort));
}
}
@Override
public void mouseEntered(MouseEvent e) {
if (e.getSource().getClass() == JLabel.class) {
JLabel l = (JLabel) e.getSource();
l.setBackground(Color.LIGHT_GRAY);
l.setForeground(Color.BLACK);
}
}
@Override
public void mouseExited(MouseEvent e) {
if (e.getSource().getClass() == JLabel.class) {
JLabel l = (JLabel) e.getSource();
l.setBackground(Color.GRAY);
l.setForeground(Color.WHITE);
}
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
}
ChatDialog
package chatroomclient;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.HashSet;
import java.util.TimerTask;
import javax.swing.*;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import chatroomsend.Send;
import chatroomutil.ChatRoomUtil; public class ChatDialog extends JFrame implements ActionListener {
private static final long serialVersionUID = 1437996471885472344L;
String myId;
String otsId;
String serverIP;
int serverPort;
JLabel chatRoomLabel = new JLabel();
JTextArea chatArea = new JTextArea();
JTextArea sendArea = new JTextArea(5, 20);
JButton sendButton = new JButton();
JScrollPane chatScroll = new JScrollPane(chatArea);
JScrollPane sendScroll = new JScrollPane(sendArea);
JPanel chatPanel = new JPanel();
JPanel sendPanel = new JPanel();
HashSet<String> friends = new HashSet<String>();
BorderLayout mainLayout = new BorderLayout();
BorderLayout chatLayout = new BorderLayout();
BorderLayout sendLayout = new BorderLayout();
ChatRoom chatRoom;
public ChatDialog(final ChatRoom chatRoom, String id, final String otsId,
String serverIP, int port) {
super(id + "与" + otsId + "聊天");
this.chatRoom = chatRoom;
this.myId = id;
this.otsId = otsId;
this.serverIP = serverIP;
this.serverPort = port;
mainLayout.setVgap(5);
sendLayout.setHgap(10);
this.setLayout(mainLayout);
chatPanel.setLayout(chatLayout);
sendPanel.setLayout(sendLayout);
chatArea.setLineWrap(true);
sendArea.setLineWrap(true);
sendButton.setText(" 发送 ");
sendButton.setBackground(Color.LIGHT_GRAY);
sendButton.addActionListener(this);
chatRoomLabel.setText("聊天");
chatArea.setEditable(false);
chatArea.setBackground(new Color(230, 230, 230));
chatPanel.add(chatRoomLabel, BorderLayout.NORTH);
chatPanel.add(chatScroll, BorderLayout.CENTER);
sendPanel.add(sendScroll, BorderLayout.CENTER);
sendPanel.add(sendButton, BorderLayout.EAST);
this.add(sendPanel, BorderLayout.SOUTH);
this.add(chatPanel, BorderLayout.CENTER);
this.setBounds(200, 200, 530, 600);
setVisible(true);
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
sendArea.addCaretListener(new CaretListener() {
@Override
public void caretUpdate(CaretEvent e) {
String str = sendArea.getText();
if (str.length() > 5000) {
ChatRoomUtil.showErrorBox("字数过多,超出限制。");
}
}
});
this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {//关闭窗口后,ChatRoom要移除该对话
chatRoom.removeDialog(otsId);
dispose();
}
});
new java.util.Timer().schedule(new TimerTask() {
public void run() {
repaint();
}
}, 400, 400);
}
public int addRecord(String mesg) {
chatArea.append(mesg + "\n");
chatArea.setCaretPosition(chatArea.getText().length());
this.validate();
return 0;
}
private String sendMessage(String mesg) {
Send sendClient = new Send();
sendClient.connect(serverIP, serverPort, 1000);
String getm = sendClient.send(
"chat" + otsId + ":" + myId + ":" + myId + ": \n" + mesg);
addRecord(myId + ": \n" + mesg);
return getm;
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource().getClass() == JButton.class) {
sendMessage(sendArea.getText());
sendArea.setText("");
}
}
}
Users.txt
1:1
2:2
3:3
4:4
5:5
6:6
7:7
8:8
9:9
10:10
11:11
12:12
13:13
14:14
15:15
16:16
17:17
18:18
19:19
20:20
21:21
22:22
23:23
24:24
25:25
26:26
27:27
28:28
29:29
30:30
31:31
32:32
33:33
34:34
35:35
36:36
37:37
38:38
39:39
40:40
41:41
42:42
43:43
44:44
45:45
46:46
47:47
48:48
49:49
50:50
51:51
52:52
53:53
54:54
55:55
56:56
57:57
58:58
59:59
60:60
61:61
62:62
63:63
64:64
65:65
66:66
67:67
68:68
69:69
70:70
71:71
72:72
73:73
74:74
75:75
76:76
77:77
78:78
79:79
80:80
81:81
82:82
83:83
84:84
85:85
86:86
87:87
88:88
89:89
90:90
91:91
92:92
93:93
94:94
95:95
96:96
aa:aa
qq:qq
ww:ww
ee:ee
guochengxin:guochengxin
huoda:huoda
zhangfa:zhangfa
hanyu:hanyu
maxuewei:maxuewei
lizeyu:lizeyu
End
写于大三下实训期间
随笔写于2016.7.13