回城传送–》《JAVA筑基100例》 文章目录零、前言今天是学习 JAVA语言 打卡的第97天,每天我会提供一篇文章供群成员阅读( 不需要订阅付钱 ),读完文章之后,按解题思路,自己再实现一遍。在小虚竹JAVA社区 中对应的 【打卡贴】打卡,今天的任务就算完成了。 因为大家都在一起学习同一篇文章,所以有什么问题都可以在群里问,群里的小伙伴可以迅速地帮到你,一个人可以走得很快,一群人可以走得很远,有一起学习交流的战友,是多么幸运的事情。 学完后,自己写篇学习报告的博客,可以发布到小虚竹JAVA社区 ,供学弟学妹们参考。 我的学习策略很简单,题海策略+ 费曼学习法。如果能把这100题都认认真真自己实现一遍,那意味着 JAVA语言 已经筑基成功了。后面的进阶学习,可以继续跟着我,一起走向架构师之路。 一、题目描述题目实现:不同的客户端之间需要进行通信,一个客户端与其他的多个客户端进行通信,实现群聊功能。 实现一个客户端与其他多个客户端进行通信,运行程序,服务器启动后,启动3个客户端程序,然后通过第一个客户端向另外两个客户端发送信息,则另外的两个客户端都会收到服务器发送的信息。 二、解题思路创建一个服务类:ClientOneToManyServerFrame,继承JFrame类 定义一个createSocket()方法,用于创建服务Socket和监听客户端程序。以及创建并启动线程对象并将接收到的客户端发送的信息转发给其他客户端。 创建一个客户端类:ClientOneToManyClientFrame,继承JFrame类 定义一个createClientSocket()方法,用于创建与服务器连接的Socket对象,输出流对象,以及启动线程对象接收服务器端转发的信息。 技术重点: 在服务器端通过线程对客户端发送的信息进行监听,当有客户端发送信息时,就会将该信息发送给其他已经登录到服务器的客户端,但是不会向发送方发送该信息,在客户端也通过线程来监听服务器转发的信息。 (2)在客户端创建线程类ClientThread,用于接收服务器端转发的客户端信息,并在客户端的文本域中显示接收到的信息。 启动多个客户端: 1、把项目打成jar包:利用maven 的clean install 会在target目录下生成jar包 2、进入target目录,使用java -cp的命令运行指定的类
进入cmd命令模式 运行服务端
运行多个客户端
三、代码详解ClientOneToManyServerFrame package com.xiaoxuzhu;import java.awt.BorderLayout;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;import java.util.Vector;import javax.swing.JFrame;import javax.swing.JScrollPane;import javax.swing.JTextArea;/** * Description: * * @author xiaoxuzhu * @version 1.0 * * <pre> * 修改记录: * 修改后版本 修改人修改日期修改内容 * 2022/6/5.1 xiaoxuzhu2022/6/5 Create * </pre> * @date 2022/6/5 */public class ClientOneToManyServerFrame extends JFrame {private JTextArea ta_info;private ServerSocket server; // 声明ServerSocket对象private Socket socket; // 声明Socket对象socketprivate Vector<Socket> vector = new Vector<Socket>();// 用于存储连接到服务器的客户端套接字对象public void createSocket() {try {server = new ServerSocket(9527);while (true) {ta_info.append("等待新客户连接......\n");socket = server.accept();// 创建套接字对象vector.add(socket);// 将套接字对象添加到向量对象中ta_info.append("客户端连接成功。" + socket + "\n");new ServerThread(socket).start();// 创建并启动线程对象}} catch (IOException e) {e.printStackTrace();}}class ServerThread extends Thread {Socket socket;public ServerThread(Socket socket) {this.socket = socket;}public void run() {try {BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));// 创建输入流对象while (true) {String info = in.readLine();// 读取信息for (Socket s : vector) {// 遍历所有客户端套接字对象if (s != socket) {// 如果不是发送信息的套接字对象PrintWriter out = new PrintWriter(s.getOutputStream(), true);// 创建输出流对象out.println(info);// 发送信息out.flush();// 刷新输出缓冲区}}}} catch (IOException e) {ta_info.append(socket + "已经退出。\n");vector.remove(socket);// 移除退出的客户端套接字}}}/** * Launch the application * * @param args */public static void main(String args[]) {ClientOneToManyServerFrame frame = new ClientOneToManyServerFrame();frame.setVisible(true);frame.createSocket();}/** * Create the frame */public ClientOneToManyServerFrame() {super();setTitle("客户端一对多通信——服务器端程序");setBounds(100, 100, 385, 266);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);final JScrollPane scrollPane = new JScrollPane();getContentPane().add(scrollPane, BorderLayout.CENTER);ta_info = new JTextArea();scrollPane.setViewportView(ta_info);}} ClientOneToManyClientFrame package com.xiaoxuzhu;import java.awt.BorderLayout;import java.awt.Dimension;import java.awt.EventQueue;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.Socket;import java.net.UnknownHostException;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JPanel;import javax.swing.JScrollPane;import javax.swing.JTextArea;import javax.swing.JTextField;/** * Description: * * @author xiaoxuzhu * @version 1.0 * * <pre> * 修改记录: * 修改后版本 修改人修改日期修改内容 * 2022/6/5.1 xiaoxuzhu2022/6/5 Create * </pre> * @date 2022/6/5 */public class ClientOneToManyClientFrame extends JFrame{private JTextArea ta_info;private JTextField tf_send;PrintWriter out;// 声明输出流对象/** * Launch the application * * @param args */public static void main(String args[]) {EventQueue.invokeLater(new Runnable() {public void run() {try {ClientOneToManyClientFrame frame = new ClientOneToManyClientFrame();frame.setVisible(true);frame.createClientSocket();} catch (Exception e) {e.printStackTrace();}}});}public void createClientSocket() {try {Socket socket = new Socket("127.0.0.1", 9527);// 创建套接字对象out = new PrintWriter(socket.getOutputStream(), true);// 创建输出流对象new ClientThread(socket).start();// 创建并启动线程对象} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}class ClientThread extends Thread {Socket socket;public ClientThread(Socket socket) {this.socket = socket;}public void run() {try {BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));// 创建输入流对象while (true) {String info = in.readLine();// 读取信息ta_info.append(info + "\n");// 在文本域中显示信息if (info.equals("88")) {break;// 结束线程}}} catch (IOException e) {e.printStackTrace();}}}private void send() {String info = tf_send.getText();// 获得输入的信息if (info.equals("")) {return;// 如果没输入信息则返回,即不发送}if (info.equals("88")) {System.exit(0);// 如果没输入信息是88,则退出}out.println(info);// 发送信息out.flush();// 刷新输出缓冲区tf_send.setText(null);// 清空文本框}/** * Create the frame */public ClientOneToManyClientFrame() {super();setTitle("客户端一对多通信——客户端程序");setBounds(100, 100, 385, 266);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);final JPanel panel = new JPanel();getContentPane().add(panel, BorderLayout.SOUTH);final JLabel label = new JLabel();label.setText("输入聊天内容:");panel.add(label);tf_send = new JTextField();tf_send.addActionListener(new ActionListener() {public void actionPerformed(final ActionEvent e) {send();// 调用方法发送信息}});tf_send.setPreferredSize(new Dimension(180, 25));panel.add(tf_send);final JButton button = new JButton();button.addActionListener(new ActionListener() {public void actionPerformed(final ActionEvent e) {send();// 调用方法发送信息}});button.setText("发 送");panel.add(button);final JScrollPane scrollPane = new JScrollPane();getContentPane().add(scrollPane, BorderLayout.CENTER);ta_info = new JTextArea();scrollPane.setViewportView(ta_info);//}} 服务器启动 客户端1向其他客户端群发信息 客户端2接收到的信息 客户端3接收到的信息 四、推荐专栏《JAVA从零到壹》 《JAVA筑基100例》 |
|