Java socket编程实现群聊
最终效果
文末有完整代码,创作不易,点个赞再走吧~
- 客户端之间的交流
- 有人退出群聊时,减少在线人数
实现流程
1、项目结构即原理分析
- 功能
- 实现多客户之间聊天
- 实时统计在线人数
- 图形化界面
- 创建昵称
- 下线通知
- 项目结构
- 原理
- 服务端:
创建socket,每次接受一个客户端来连接,就分配一个线程处理和客户端通信,将昵称和服务器分配给其的输出流存储,然后实现群聊 - 客户端
客户端继承JFrame框架,添加组件。创建客户端的socket,输入昵称,创建客户端socket对应的输入流和输出流
2、代码分析
2.1、客户端图形化界面设计
public class ClientFrame {
public void frame() {
JFrame frame = new JFrame();
frame.setTitle("客户端");
ClientPanel panel = new ClientPanel();
panel.panel();
//panel添加到窗体里面
frame.add(panel);
//布局置空,设置绝对定位
frame.setLayout(null);
frame.setBounds(100, 100, 900, 500);
//设置窗口不可变
frame.setResizable(true);
//设置窗口可见
frame.setVisible(true);
//设置背景颜色
// frame.getContentPane().setBackground(Color.MAGENTA);
//关闭窗体
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
2.2、客户端面板模块
public void panel() {
setBounds(30, 30, 800, 410);
// setBackground(LIGHT_GRAY);
setFocusable(true);//设置获取焦点
setLayout(null);//布局自定义
/*lab_ip*/
JLabel lab_ip = new JLabel("IP:");
lab_ip.setBounds(10, 10, 50, 30);
lab_ip.setFont(new Font("宋体", Font.BOLD, 20));//字体样式
lab_ip.setForeground(black);//标签字体前景色
/*ip框*/
JTextField ip = new JTextField(20);
ip.setBounds(60, 10, 180, 30);
ip.setFont(new Font("微软雅黑", Font.BOLD, 20));
/*端口*/
JLabel lab_port = new JLabel("端口:");
lab_port.setBounds(240, 10, 80, 30);
lab_port.setFont(new Font("宋体", Font.BOLD, 20));//字体样式
lab_port.setForeground(black);//标签字体前景色
//用户名称
JLabel username = new JLabel("用户名:");
username.setBounds(450, 10, 80, 30);
username.setFont(new Font("宋体", Font.BOLD, 20));//字体样式
username.setForeground(black);//标签字体前景色
//用户名框
JTextField usernameport = new JTextField(10);
usernameport.setBounds(550, 10, 100, 30);
usernameport.setFont(new Font("微软雅黑", Font.BOLD, 20));
/*端口框*/
JTextField port = new JTextField(10);
port.setBounds(320, 10, 100, 30);
port.setFont(new Font("微软雅黑", Font.BOLD, 20));
/*连接按钮*/
JButton connection = new JButton("连接");
connection.setBounds(700, 10, 100, 30);
connection.setBackground(green);
/*状态标签*/
JLabel flag = new JLabel("");
flag.setBounds(230, 30, 100, 35);
/*接收框*/
TextArea textRec = new TextArea("");
textRec.setBounds(90, 70, 600, 180);
textRec.setFont(new Font("微软雅黑", Font.PLAIN, 20));
/*输入框*/
TextArea textSend = new TextArea(1, 10);
textSend.setColumns(20);
textSend.setBounds(90, 260, 600, 70);
textSend.setFont(new Font("微软雅黑", Font.BOLD, 20));
textSend.setBackground(white);
/*发送按钮*/
JButton btn_en = new JButton("发送");
btn_en.setBounds(440, 350, 100, 40);
btn_en.setBackground(pink);
/*在线人数lab*/
JLabel jLabel = new JLabel("在线人数:");
jLabel.setBounds(0, 70, 90, 35);
jLabel.setFont(new Font("微软雅黑", Font.PLAIN, 20));
/*人数*/
JLabel online = new JLabel("");
online.setBounds(30, 120, 100, 18);
online.setFont(new Font("微软雅黑", Font.PLAIN, 18));
online.setText("");
add(lab_ip);
add(ip);
add(lab_port);
add(username);
add(usernameport);
add(port);
add(connection);
add(flag);
add(textRec);
add(textSend);
add(btn_en);
}
2.3、服务端的转发信息方法
//接收消息
public String receiveTest(Socket socket) throws IOException {
inputStream = socket.getInputStream();
byte[] bytes = new byte[1024];
int len = inputStream.read(bytes);
return new String(bytes, 0, len);
}
//转发其他客户端方法
public void sendOther(Socket socket, String msg) throws IOException {
for (Socket client : ServerTest.list) {
if (client == socket) {
//2.是自己返回带标记的消息
outputStream = socket.getOutputStream();
InetAddress localAddress = socket.getLocalAddress();
//是自己的返回消息类型
outputStream.write(("len" + msg +"\r\n\n").getBytes