Chat Room
孙嘉悦
2023-12-01
package cy;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
public class ChatRoomServer extends Frame implements Runnable {
Panel panel;
ScrollPane sPanel;
TextArea textArea;
Button button1;
// net
ServerSocket serverSock;
public final static int DEFAULT_PORT = 6666;// 默认端口号
Thread chatAcceptThread;// 启动接受连接的线程
BroadcastThread broadcastThread;// 广播thread; run when server is listening
java.util.Vector clients;// 记录连接的线程
java.util.Vector clientsInfor;// 记录连接线程的信息
public static int index = 0;
public ChatRoomServer() {
try {
jbInit();
} catch (Exception e) {
e.printStackTrace();
}
serverListen();// 服务器开始监听
}
private void jbInit() {// 初始化界面
panel = new Panel();
sPanel = new ScrollPane();
textArea = new TextArea("server information:/n");
button1 = new Button("退出");
sPanel.add(textArea);
button1.addActionListener(new java.awt.event.ActionListener() {// 退出按钮注册
public void actionPerformed(ActionEvent e) {
button1_actionPerformed(e);
}
});
panel.add(button1);
this.addWindowListener(new ChatFrame_WindowAdapter(this));// 注册到继承了窗口适配器的类
this.setSize(600, 600);
this.setLayout(new BorderLayout());
this.add(sPanel, BorderLayout.CENTER);
this.add(panel, BorderLayout.SOUTH);
this.show();
}
private void button1_actionPerformed(ActionEvent e) {
exit();
}
public void processMsg(String str) {//
textArea.append(str);
}
private void serverListen() {
try {
serverSock = new ServerSocket(DEFAULT_PORT);
} catch (IOException e) {
processMsg(e.toString());
processMsg("server failed!/n");
}
processMsg("server listening on port:" + DEFAULT_PORT);
clients = new java.util.Vector();
clientsInfor = new java.util.Vector();
chatAcceptThread = new Thread(this);// 启动接受连接的线程
chatAcceptThread.start();
broadcastThread = new BroadcastThread(this);// 广播线程
broadcastThread.start();
// 还有一个回收无用连接thread 的线程
}
public void run() {// 接受连接并记录线程信息
int i = 0;
try {
while (true) {
Socket clientSock = serverSock.accept();
CommunicateThread ct = new CommunicateThread(clientSock, this,
index);// 创建线程保持连接
clients.add(ct);// record Communicate Thread;
i++;
index++;// version2
clientsInfor.add("Thread-" + i);
processMsg("Thread-" + i + "join in/n");
}
} catch (IOException e) {
processMsg(e.toString());
}
}
public void exit() {
broadcastThread.broadcast("Server exit!");
try {
serverSock.close();
} catch (IOException ioe) {
} finally {
System.exit(0);
}
}
public static void main(String[] args) {
ChatRoomServer chat = new ChatRoomServer();
}
}
class CommunicateThread extends Thread {// 保持连接线程
protected Socket clientSock;
protected BufferedReader in = null;
protected PrintWriter out;
ChatRoomServer chatFrame;
boolean isTrue = true;// run()
java.util.Vector inforStack;
int index2;//
public CommunicateThread(Socket Sock, ChatRoomServer cFrame, int index) {
clientSock = Sock;
chatFrame = cFrame;
index2 = index;
inforStack = new java.util.Vector();
try {
in = new BufferedReader(new InputStreamReader(clientSock
.getInputStream()));
out = new PrintWriter(clientSock.getOutputStream());
} catch (IOException ei) {
try {
clientSock.close();
} catch (IOException ei2) {
}
chatFrame.processMsg(ei.toString());
return;
}
this.start();
}
public void run() {
String infor;
try {
while (isTrue) {
infor = in.readLine();
if (infor.equals("Client exit!")) {
writeInformation(infor);// 把信息写到信息栈,以倍广播出去
stopRun();
} else if (infor != null) {
writeInformation(infor);
}// else break;
try {
Thread.sleep(100);// version2
} catch (InterruptedException ex) {
}
}
} catch (IOException e) {
;
} finally {
try {
in.close();
out.close();
clientSock.close();
chatFrame.clients.remove(index2);// 在clients中清除本线程序
ChatRoomServer.index--;//
} catch (IOException ei) {
;
}
}
}
public void writeInformation(String infor) {// 写信息栈
inforStack.add(infor);
}
private void stopRun() {// 终止线程
isTrue = false;
}
public void sendInformation(String str) {// 发送信息
try {
out.println(str);
out.flush();
} catch (Exception e) {
;
}
}
}
class BroadcastThread extends Thread {// 广播线程
ChatRoomServer chatFrame2;
java.util.Vector chatClients;// 连接线程信息
java.util.Vector msgStack;// 信息栈
java.util.Vector clientMsg;// 记录客户发送的信息
CommunicateThread comThread1;
CommunicateThread comThread2;
String string;// information in inforStack
String clientName;// client thread name
String broadcastInfor;// broadcast information=clientName+string;
public BroadcastThread(ChatRoomServer cFrame) {
chatFrame2 = cFrame;
chatClients = chatFrame2.clients;
clientMsg = chatFrame2.clientsInfor;
// this.start();
}
public void broadcast(String str) {// 广播
for (int k = 0; k < chatClients.size(); k++) {// send to
// everyone分别调用每个连接线程,发送信息
comThread2 = (CommunicateThread) chatClients.get(k);
comThread2.sendInformation(str);
}
}
public void run() {
try {
while (true) {
for (int i = 0; i < chatClients.size(); i++) {
comThread1 = (CommunicateThread) chatClients.get(i);
msgStack = comThread1.inforStack;// 得到每个连接的信息栈
clientName = (String) clientMsg.get(i);// 客户名
// 读取每个连接线程的信息栈并把信息发送出去
for (int j = 0; j < msgStack.size(); j++) {
string = (String) msgStack.get(j);
broadcastInfor = clientName + "->" + string;
broadcast(broadcastInfor);
}
// clear the inforStack
msgStack.removeAllElements();// 清除以发送的信息
}
try {
Thread.sleep(100);// version2
} catch (InterruptedException ex) {
}
}
} catch (Exception e) {
}
}
}
// 处理窗口关闭事件的适配器
class ChatFrame_WindowAdapter extends java.awt.event.WindowAdapter {
ChatRoomServer chatFrame;
public ChatFrame_WindowAdapter(ChatRoomServer chatFrame) {
this.chatFrame = chatFrame;
}
public void windowClosing(WindowEvent e) {// exit program
chatFrame.exit();// reference to the method exit() in ChatRoomServer.
}
}
======================
package cy;
//ChatRoomClient
//designed by Chen Heping(陈和平)
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
public class ChatRoomClient extends Frame implements Runnable {
Panel panel1, panel2;
Button button1, button2;
TextField textField1, textField2;
Label label1;
TextArea textArea;
ScrollPane sPanel;
// net
PrintWriter out;
BufferedReader in = null;
Socket sock;
public final static int DEFAULT_PORT = 6666;
// create Thread to Read information from Server
Thread readThread;
boolean isTrue = true;// thread can go on runing ??
public ChatRoomClient() {
try {
jbInit();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {// main method
ChatRoomClient c = new ChatRoomClient();
c.show();
}
private void jbInit() {// should set size,position and Font of every
// component
button1 = new Button("连接");// set Font
button2 = new Button("发送");
textField1 = new TextField("input Server address here!");
textField2 = new TextField("input Message here and send to server");
label1 = new Label("消息:");
panel1 = new Panel();
panel2 = new Panel();
sPanel = new ScrollPane();
textArea = new TextArea();
// panel1
// press button1: 连接 to connect the client to server
button1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
button1_actionPerformed(e);
}
});
// textField1:for input the address of server;be registered to
// KeyListener.
// press key:Enter to connect the client to server
textField1.addKeyListener(new textField1_KeyAdapter(this));// java.awt.event.KeyAdapter()
panel1.add(button1);
panel1.add(textField1);
// sPanel ScrollPane
sPanel.add(textArea);
// panel2
// press button2: 发送 to send message
button2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
button2_actionPerformed(e);
}
});
// textField2:for input message;be registered to KeyListener.
// press key:Enter to send message
textField2.addKeyListener(new textField2_KeyAdapter(this));
panel2.add(label1);
panel2.add(textField2);
panel2.add(button2);
// frame
this.addWindowListener(new ChatFrame_WindowAdapterClient(this));// frame
// is
// registered to
// WindowListener
this.setLayout(new BorderLayout());
this.setSize(500, 400);
this.add(panel1, BorderLayout.NORTH);
this.add(sPanel, BorderLayout.CENTER);
this.add(panel2, BorderLayout.SOUTH);
// this.show()
}
public void startConnect() {// 开始连接
try {
sock = new Socket(textField1.getText(), DEFAULT_PORT);
if (sock != null) {// connection successed
processMsg("Connect successfully!");
}
in = new BufferedReader(
new InputStreamReader(sock.getInputStream()));
out = new PrintWriter(sock.getOutputStream());
} catch (IOException ex) {
processMsg(ex.toString());
processMsg("Connect failed!");
}
readThread = new Thread(this);
readThread.start();
}
// public void endConnect(){//close IOstream
public void sendInformation() {
out.println(textField2.getText());
out.flush();
}
private void button1_actionPerformed(ActionEvent e) {// 连接按钮
startConnect();
}
private void button2_actionPerformed(ActionEvent e) {// 发送按钮
sendInformation();
}
public void stopRun() {// to stop the running thread
isTrue = false;
}
public void processMsg(String msg) {// 客户端处理消息
textArea.append(msg);
textArea.append("/n");
}
public void run() {
String msg;
isTrue = true;
while (isTrue) {
try {
msg = in.readLine();
if (msg.equals("Server exit!")) {// server exit
processMsg(msg);
stopRun();// 终止线程
} else if (msg != null) {
processMsg(msg);
}
Thread.sleep(1000);
} catch (IOException e) {
processMsg(e.toString());
} catch (InterruptedException ei) {
processMsg(ei.toString());
}
}
// endConnect();
try {// 服务器退出关闭连接和相关的"流"
sock.close();
in.close();
out.close();
} catch (IOException ioe) {
}
}
public void exit() {// 窗口关闭;如果有连接则关闭连接和相关的"流"
try {// send "Client exit!" to Server!
out.println("Client exit!");
out.flush();
} catch (Exception exc) {
}
// endConnect();
try {// close IOstream
sock.close();
in.close();
out.close();
} catch (IOException ioe) {
} finally {
System.exit(0);
}
}
}
// 文本筐textField1的键击事件适配器
class textField1_KeyAdapter extends java.awt.event.KeyAdapter {
ChatRoomClient chatFrame;
public textField1_KeyAdapter(ChatRoomClient chatFrame) {
this.chatFrame = chatFrame;
}
public void keyPressed(KeyEvent e) {// 输入的是enter,开始连接!
int j = e.getKeyCode();
if (j == e.VK_ENTER) {
chatFrame.startConnect();
}
}
}
// 文本筐textField2的键击事件适配器
class textField2_KeyAdapter extends java.awt.event.KeyAdapter {
ChatRoomClient chatFrame;
public textField2_KeyAdapter(ChatRoomClient chatFrame) {
this.chatFrame = chatFrame;
}
public void keyPressed(KeyEvent e) {// 键击Enter键,发送信息!
int j = e.getKeyCode();
if (j == e.VK_ENTER) {
chatFrame.sendInformation();
}
}
}
// 窗口关闭事件适配器
class ChatFrame_WindowAdapterClient extends java.awt.event.WindowAdapter {
ChatRoomClient chatFrame;
public ChatFrame_WindowAdapterClient(ChatRoomClient chatFrame) {
this.chatFrame = chatFrame;
}
public void windowClosing(WindowEvent e) {// exit program
chatFrame.exit();// reference to the method exit() in ChatRoomClient.
}
}