javasocket编程实现群聊(超详细)(代码片段)

乘凉者栽树人 乘凉者栽树人     2022-12-08     719

关键词:

Java socket编程实现群聊

最终效果

文末有完整代码,创作不易,点个赞再走吧~

  • 客户端之间的交流
  • 有人退出群聊时,减少在线人数

实现流程

1、项目结构即原理分析

  • 功能
  1. 实现多客户之间聊天
  2. 实时统计在线人数
  3. 图形化界面
  4. 创建昵称
  5. 下线通知
  • 项目结构
  • 原理

  1. 服务端:
    创建socket,每次接受一个客户端来连接,就分配一个线程处理和客户端通信,将昵称和服务器分配给其的输出流存储,然后实现群聊
  2. 客户端
    客户端继承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());

             //客户端是自己不转发
             continue;
         
         //输出对应客户端socket
         outputStream = client.getOutputStream();
         SocketAddress socketAddress = client.getLocalSocketAddress();
         //分割字符串,从第一个开始
         outputStream.write(( msg+"\\r\\n\\n").getBytes());
         System.out.println("已转发=>" + msg);

     

2.4、服务器统计在线人数

//统计在线人数
    public void onLine() 
        int num = ServerTest.list.size();

        List<Socket> sockets = ServerTest.list;
        for (Socket client : sockets) 
            try 
                outputStream = client.getOutputStream();
                outputStream.write(("\\n        【当前在线人数:" + num + "】\\n").getBytes());
             catch (IOException e) 
                e.printStackTrace();
            
        
    

2.5、启动服务器供多客户连接

public class ServerTest 

    //客户端集合
    protected static List<Socket> list = new ArrayList<>();

    public static void main(String[] args) 
        Service service = null;
        try 
            int i = 0;
            ServerSocket serverSocket = new ServerSocket(8848);
            while (true) 
                //一直接受客户端请求,多客户端连接
                Socket socket = serverSocket.accept();
                list.add(socket);

                //服务线程
                service = new Service(socket);

                //开启线程
                new Thread(service).start();

                service.onLine();
                System.out.println("socket=" + socket);
                System.out.println("主线程循环" + i++ + "次");
                System.out.println("客户端在线数:" + list.size());
            
         catch (IOException e) 
            e.printStackTrace();
            service.onLine();//出异常再次调用通知人数方法
        
    

2.6、写一个ip地址和端口号供客户端连接

 public static void main(String[] args) 
        try 
            ClientBase clientBase = new ClientBase("127.0.0.1",8848);
            clientBase.sendTest("hello world","hello world");
            System.out.println(clientBase.receiveTest());
         catch (IOException e) 
            e.printStackTrace();
        
  

2.7、发送以及接收方法

 /**
    * 发送方法
    */
   public void sendTest(String username ,String msg) throws IOException 
       //获取 字节输出流
       if (msg.length() != 0) 
           outputStream = socket.getOutputStream();
           String sum =username+"说: "+msg;
           outputStream.write(sum.getBytes("UTF-8"));
       
   

   /**
    * 接收方法
    *
    * @return 接收内容
    */
   public String receiveTest() throws IOException 
       //获取服务器回应消息
       inputStream = socket.getInputStream();
       byte[] bytes = new byte[1024];
       int len = inputStream.read(bytes);
       try 
           string = new String(bytes, 0, len, "UTF-8");
        catch (IOException e) 
           System.out.println("error");
       
       return string;
   

2.8、接收到统计的在线人数

 /*接收在线人数*/
 public String onLine() 
     String str = "";
     InputStream inputStream = null;
     try 
         inputStream = socket.getInputStream();
         byte[] bytes = new byte[1024];
         int len = inputStream.read(bytes);
         str = new String(bytes, 0, len);
      catch (IOException e) 
         e.printStackTrace();
         try 
             inputStream.close();
          catch (IOException ioException) 
             ioException.printStackTrace();
         
     
     return str;
 

2.9、回到面板写入监听事件

//连接事件监听
       connection.addActionListener(new ActionListener() 
           @Override
           public void actionPerformed(ActionEvent e) 
               try 
                   clientBase = new ClientBase(ip.getText(), Integer.parseInt(port.getText()));
                catch (IOException ioException) 
                   flag.setText("未连接");
                   flag.setForeground(red);
               
               Socket socket = clientBase.getSocket();
               if (flag.getText().equals("已连接") && clientBase != null) 

                else if (socket != null)
                   try 
                       flag.setText("已连接");
                       flag.setForeground(green);
                       //接收线程
                       new Thread(new Runnable() 
                           private boolean f = true;//线程标志位

                           @Override
                           public void run() 
                               //接收消息
                               while (f) 
                                   try 
                                       String text = clientBase.receiveTest();
                                       //判断转回的消息是不是自己的
                                       String temp = text.substring(0, 3);//截取前三位字符,注意不包括3  [0,3)
                                       //是否以len开始
                                       if (text.startsWith("len")) 
                                          // textRec.setForeground(blue);
                                           //追加收到内容
                                           textRec.append(text.substring(3));//截取第三个到末尾的字符串

                                        else 
                                           textRec.setForeground(black);
                                           textRec.append(text);
                                       
                                    catch (IOException ioException) 
                                       flag.setText("连接重置");
                                       flagandroidapp实战项目之仿微信的私信和群聊app(附源码和演示视频超详细必看)(代码片段)

需要全部代码请点赞关注收藏后评论区留言私信~~~手机最开始用于通话,后来增加了短信功能,初步满足了人与人之间的沟通需求。然而短信只能发文字,于是出现了能够发图片的彩信,但不管短信还是彩信,... 查看详情

javasocket编程学习笔记

 1.Socket通信简介及模型  JavaSocket可实现客户端--服务器间的双向实时通信。java.net包中定义的两个类socket和ServerSocket,分别用来实现双向连接的client和server端。2.Socket通信实现方法 2.1 服务器端(非多线程)   用... 查看详情

javasocket详解(代码片段)

整理和总结了一下经常遇到的问题:1.客户端socket发送消息后,为什么服务端socket没有收到?2.使用while循环实现连续输入,是不是就是多线程模式?3.对多线程处理机制不是很明白,希望详细讲解?4.希... 查看详情

c++入门c和c++混合编程超详细讲解(代码片段)

1、为什么需要C和C++混合编程(1)C++是在C语言的基础上发展出来的,在C++发明之前已经用C语言实现了很多功能库,C++要使用这些库就涉及到调用C语言;(2)C++和C语言各自有更适合的领域ÿ... 查看详情

javasocket实现udp编程

UDP简介UDP是UserDatagramProtocol的简称,中文名是用户数据报协议,是OSI(OpenSystemInterconnection,开放式系统互联)参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETFRFC768是... 查看详情

三子棋(九宫棋)游戏的实现(详细片)(代码片段)

目录1.前言2.游戏准备3.实现游戏的步骤(1)生成菜单界面(2)游戏的实现逻辑1.棋盘的初始化2.生成九宫格3.玩家下棋4.电脑下棋5.判断输赢(3)额外补充(实现游戏先手或者后手的代码)(4)额... 查看详情

tensorflow逻辑回归原理与实现(超详细)

...3.2导数计算图3.3链式法则3.4逻辑回归的梯度下降4.向量化编程4.1向量化优势4.2向量化实现伪代码5.案例:实现逻辑回归5.1使用数据:制作二分类数据集5.2步骤设计学习目标目标知道逻辑回归的算法计算输出、损失函数知道... 查看详情

javasocket编程学习笔记

在上一篇中,使用了javaSocket+Tcp/IP 协议来实现应用程序或客户端--服务器间的实时双向通信,本篇中,将使用UDP协议来实现Socket的通信。1.关于UDP  UDP协议(用户数据报协议)是无连接的、不可靠的、无序的,速度快,进行... 查看详情

javasocket实现服务端,客户端简单网络通信。chat

之前写的实现简单网络通信的代码,有一些严重bug。后面详细写。根据上次的代码,主要增加了用户注册,登录页面,以及实现了实时显示当前在登录状态的人数。并解决一些上次未发现的bug。(主要功能代码参见之前随笔https://... 查看详情

python进阶多任务编程(超详细)(代码片段)

Python多任务编程1.多任务的介绍2.进程3.多进程的使用4.获取进程编号5.进程执行带有参数的任务6.进程的注意点7.线程8.多线程的使用9.线程执行带有参数的任务10.线程的注意点11.互斥锁12.死锁13.进程和线程的对比1.多任务的介绍1.... 查看详情

手把手教你c语言队列实现代码,通俗易懂超详细!

大家好,我是无际。近期我们无际单片机编程分享的高级程序架构教程受到了很多粉丝们的高度好评和认可。这个教程只要用心看的都能体会到里面巨大的价值,特别是工作经验在2-3年的。我们整个教程里面有一章节是... 查看详情

javasocket编程(代码片段)

Socket概念tcp协议全称是TransmissionControlProtocol,传输控制协议,是以字节流的方式发送数据的协议。ip全称为InternetProtocol互联网协议,tcp/ip协议在四层模型中的传输层。http、ftp、telnet(ssh)远程登录服务为应用层协议࿰... 查看详情

手动搭建i/o网络通信框架2:bio编程模型实现群聊(代码片段)

...Socket和ServerSocket简单的实现了网络通信。这一章,利用BIO编程模型进行升级改造,实现群聊聊天室。    如图:当一个客户端请求进来时,接收器会为这个客户端分配一个工作线程,这个工作线程专职处理客户端的操作。在... 查看详情

tensorflow案例:实现线性回归(超详细)(代码片段)

案例:实现线性回归学习目标1.线性回归原理复习2.案例:实现线性回归的训练2.1案例确定2.2API2.3步骤分析2.4实现完整功能2.5变量的trainable设置观察2.6增加其他功能2.6.1增加命名空间3.模型的保存与加载4.命令行参数使用5.... 查看详情

网络i/o编程模型16netty框架实现的群聊系统(代码片段)

一背景描述1.编写一下群聊系统:实现服务器端和客户端之间数据通讯(非阻塞模式)服务端:可以检测用户上线,离线,并实现消息转发功能。客户端:通过channel可以无阻塞发送消息给其他所用用户&... 查看详情

echarts实现数据可视化入门教程(超详细)(代码片段)

ECharts实现数据可视化入门教程(超详细)ECharts介绍ECharts入门教程第一步:下载并引入scharts.js文件第二步:编写代码目录结构编写index.html代码效果展示ECharts的基础配置主要配置(常用的)案例讲解补充示... 查看详情

超详细博客入门编写教程(代码片段)

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左... 查看详情

基于pytorch实现图片去模糊降噪,超详细,有代码,数据,可直接运行。

教大家一下,图片去模糊降噪的基本方法和完整的实验流程。目录简介:环境配置 参数设置数据显示 查看详情