C/S模式多人聊天室
? 在IDEA下创建ChatRoom项目,在该项目下创建ChatClient和ChatServer两个Moudule,分别是聊天室的客户端和服务器端。
1. 登录界面和客户端界面创建
创建登陆界面
效果展示:
创建Login.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Login extends JFrame {
private JLabel unameJLabel;
private JLabel pwdJLabel;
private JTextField unameJTextFiled;
private JTextField pwdJTextFiled;
private JButton loginJButton;
private JButton cancelJButton;
public Login(){
super("聊天室");
this.unameJLabel = new JLabel("用户名:");
this.pwdJLabel = new JLabel("密码:");
this.unameJTextFiled = new JTextField();
this.pwdJTextFiled = new JTextField();
this.loginJButton = new JButton("登录");
this.cancelJButton = new JButton("取消");
this.setSize(300,200);
this.setLayout(new GridLayout(3,2));
this.add(unameJLabel);
this.add(unameJTextFiled);
this.add(pwdJLabel);
this.add(pwdJTextFiled);
this.add(loginJButton);
this.add(cancelJButton);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
}
创建ClientMain主函数启动
public class ClientMain {
public static void main(String[] args) {
new Login();
}
}
给登录按钮绑定监听事件
class MyEvent implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
String loginuname = unameJTextFiled.getText();
try {
Socket socket = new Socket("127.0.0.1",9999);
new Client(socket,loginuname);
dispose();
} catch (UnknownHostException ex) {
JOptionPane.showMessageDialog(null,"找不到服务器");
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
this.loginJButton.addActionListener(new MyEvent());
点击登录后,由登录界面跳转到客户端界面
创建客户端界面
Client.java
import javax.swing.*;
import java.net.Socket;
public class Client extends JFrame{
private JScrollPane topPanel;
private JPanel bottomPanel;
private JTextArea msgList;
private JTextField msgText;
private JButton sendButton;
private Socket socket;
private String uname;
public Client(Socket socket,String uname){
super(uname);
this.socket = socket;
this.uname = uname;
this.topPanel = new JScrollPane();
this.bottomPanel = new JPanel();
this.msgList = new JTextArea();
this.msgText = new JTextField();
this.sendButton = new JButton("发送");
this.topPanel.setLayout(null);
this.bottomPanel.setLayout(null);
this.topPanel.setBounds(0,0,1000,500);
this.msgList.setBounds(30,30,940,440);
this.bottomPanel.setBounds(0,500,1000,100);
this.msgText.setBounds(30,510,700,80);
this.sendButton.setBounds(750,510,200,80);
this.topPanel.add(msgList);
this.bottomPanel.add(msgText);
this.bottomPanel.add(sendButton);
this.add(topPanel);
this.add(bottomPanel);
this.setSize(1000,650);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
}
2. 服务器端接收消息和群发消息
- 服务器端接收到客户端发来的所有socket,并转发给所有客户端,需要使用多线程,一边接收,一边群发消息
- 输入输出流的封装!!!
Server.java
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class Server {
private List<Socket> clientSockets = new ArrayList<Socket>();
public Server(){
try {
ServerSocket serverSocket = new ServerSocket(9999);
while (true){
Socket socket = serverSocket.accept();
this.clientSockets.add(socket);
ReceiveThread thread = new ReceiveThread(socket);
thread.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
class ReceiveThread extends Thread{
private Socket currentSocket;
public ReceiveThread(Socket socket){
this.currentSocket = socket;
}
@Override
public void run() {
try {
InputStream is = this.currentSocket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
String msg = null;
while ((msg = bufferedReader.readLine()) != null){
for (Socket socket:clientSockets){
PrintWriter pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
pw.println(msg);
pw.flush();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3. 客户端发送和接收消息
在客户端中开启一个接收线程接收来自服务器的消息,并监听发送按钮,向服务器端发送消息
class MyEvent implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
String msg = msgText.getText();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String time = simpleDateFormat.format(new Date());
msg = time + uname +"说:"+msg;
try {
PrintWriter pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
pw.println(msg);
pw.flush();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
class ReceiveThread extends Thread{
@Override
public void run() {
BufferedReader bufferedReader;
try {
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String msg = null;
while ((msg = bufferedReader.readLine()) != null){
msgList.append(msg+"\n");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
开启接收线程和给发送按钮绑定监听事件:
ReceiveThread receiveThread = new ReceiveThread();
receiveThread.start();
this.sendButton.addActionListener(new MyEvent());
4. 运行效果演示:
tips:
IDEA中开启多窗口运行同一个程序:点击Edit Configurations,勾选Allow Parallel Run,并Apply即可
5. 项目改进
?
|