java实现网络聊天

 网络聊天实现步骤(从功能谈论方法):

客户端:

1.登录面板:注册提醒用户注册格式,登录账号密码不为空,点击登录的时候需要连接服务器端,启动聊天面板。(监听用户点击登录,这时候连接服务器)

2.聊天面板:消息框接收服务器端发送的消息,发送消息框保存消息内容,点击发送按钮将发送消息框递给服务器端(需要创造一个线程不断监听服务器端发送回来的消息,并且显示在消息框)

服务器端:

1.服务器端需要循环监听客户端发送过来的连接

2.把循环接收到的多个客户端用集合储存起来

3.为每个客户端建立一个线程,用来接收他们发送的消息并且为其他客户端转送消息。

4.发送公告功能:聊天面板,发送公告面板,发送按钮(将发送面板的消息发送给各个客户端)。

客户端启动界面
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.Socket;

public class Logon extends JFrame {
    public Logon() {

        this.setTitle("欢迎登录");
        this.setSize(400, 400);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


        //标签
        JLabel jLabel = new JLabel("欢迎登录");
        jLabel.setFont(new Font("楷体", Font.BOLD, 20));//字体
        jLabel.setForeground(new Color(21, 12, 12));
        JPanel jPanel = new JPanel();
        jPanel.add(jLabel);
        //账号
        JPanel jPanel1 = new JPanel();
        JLabel jLabel1 = new JLabel("账号");
        JTextField jTextField1 = new JTextField(15);
        jPanel1.add(jLabel1);
        jPanel1.add(jTextField1);
        //密码
        JPanel jPanel2 = new JPanel();
        JLabel jLabel2 = new JLabel("密码");
        JTextField jTextField2 = new JTextField(15);
        jPanel2.add(jLabel2);
        jPanel2.add(jTextField2);
        //按钮
        //登录
        JButton jButton = new JButton("登录");
        jButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (jTextField1.getText().equals("") || jTextField2.getText().equals("")) {
                    JOptionPane.showMessageDialog(null, "请输入");
                } else {
                    try {
                        Socket socket = new Socket("192.168.124.89", 9999);
                        new ChatMap(jTextField1.getText(),socket);
                        dispose();
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                        JOptionPane.showMessageDialog(null, "没有连接至服务器,请稍后");
                    }
                }
            }
        });
        //注册
        JButton jButton1 = new JButton("注册");
        jButton1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (!jTextField1.getText().matches("\\w*") || !jTextField2.getText().matches("\\w*")) {
                    JOptionPane.showMessageDialog(null, "只支持大小写字母及数字");
                }
            }
        });
        JPanel jPanel3 = new JPanel();
        jPanel3.add(jButton);
        jPanel3.add(jButton1);

        this.setLayout(new GridLayout(4, 1));
        this.add(jPanel);
        this.add(jPanel1);
        this.add(jPanel2);
        this.add(jPanel3);

        this.setVisible(true);//让窗口显示,放在代码的最后一行。
    }
}

客户端聊天界面
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ChatMap extends JFrame {

    JTextArea jTextArea;

    public ChatMap(String account, Socket socket) throws IOException {
        //向服务器发送信息
        DataOutputStream dataOutputStream=new DataOutputStream(socket.getOutputStream());

        this.setTitle("欢迎来到"+account+"聊天室");
        this.setSize(400, 400);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //创造面版
        JPanel jPanel = new JPanel(new BorderLayout());

        //聊天窗口
        jTextArea = new JTextArea(20, 15);
        jTextArea.setEnabled(false);
        jTextArea.setLineWrap(true);
        JScrollPane jScrollPane = new JScrollPane(jTextArea);
        jPanel.add(jScrollPane,BorderLayout.NORTH);
        //输入窗口
        JTextArea jTextArea1 = new JTextArea(1, 10);
        jTextArea.setLineWrap(true);
        JScrollPane jScrollPane1 = new JScrollPane(jTextArea1);
        jPanel.add(jScrollPane1,BorderLayout.CENTER);

        //按钮
        JButton jButton=new JButton("发送");
        jButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
              String message=jTextArea1.getText();
              if(message.length()==0)//为什么要依靠message长度判断
              {
                  JOptionPane.showMessageDialog(null, "输入不能为空");
                  return;
              }
              //不为空显示日期向服务器发送信息
                Date date=new Date();
                SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String str=sdf.format(date);
                String msg=account+":"+str+"\n";
                msg+=message;

                try {
                    dataOutputStream.writeUTF(msg);//发送消息
                    jTextArea1.setText("");//清空发送框
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                    JOptionPane.showMessageDialog(null, "内容发送失败,请检查网络");
                }

            }
        });
        jPanel.add(jButton,BorderLayout.EAST);

        this.add(jPanel);
        this.setVisible(true);//让窗口显示,放在代码的最后一行。

        //面板创造完毕建立监听(服务器传入的消息)
        new BThread(socket,jTextArea).start();
    }
    //内部类监听服务器端
    class BThread extends Thread
    {
        DataInputStream dataInputStream;

       public BThread(Socket socket,JTextArea jTextArea) throws IOException {
          dataInputStream=new DataInputStream(socket.getInputStream());

       }

        @Override
        public void run() {
            while(true)//循环条件:退出
            {
                try {
                    String message=dataInputStream.readUTF();
                    jTextArea.append(message+"\n");
                } catch (IOException e) {
                    e.printStackTrace();
                    System.out.println("服务器断开连接");

                    break;//停止客户端线程
                }
            }
        }
    }

}

 

启动客户端
public class Run {
    public static void main(String[] args) {
        new Logon();
    }
}
服务器端界面
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class server extends JFrame {
    ArrayList<Socket> sockets=new ArrayList<>();
    Socket socket;
    JTextArea jTextArea;
    JTextArea  jTextArea1;
    JButton jButton;
    public server(){
        //设置窗口
        this.setTitle("服务器");
        this.setSize(400, 400);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel jPanel=new JPanel(new BorderLayout());

        jTextArea=new JTextArea();
        jTextArea.setEnabled(false);//不可进行操作
        jTextArea.setLineWrap(true);
        JScrollPane jScrollPane=new JScrollPane(jTextArea);

        //发送
        JPanel jPanel1=new JPanel();
        jTextArea1=new JTextArea();
        jTextArea1.setEnabled(true);//可进行操作
        jTextArea1.setLineWrap(true);
        JScrollPane jScrollPane1=new JScrollPane(jTextArea1);

        jButton=new JButton("发送");
        jButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String massage=jTextArea1.getText();
                for (Socket s:sockets)
                {
                    DataOutputStream dOut= null;
                    try {
                        dOut = new DataOutputStream(s.getOutputStream());
                        dOut.writeUTF("公告:"+massage);
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                        JOptionPane.showMessageDialog(null, "发送失败");
                    }

                }
            }
        });


        jPanel1.add(jScrollPane1);
        jPanel1.add(jButton);

        jPanel.add(jScrollPane);
        jPanel.add(jPanel1,BorderLayout.SOUTH);

        this.add(jPanel);
        this.setVisible(true);
        //启动服务器
        this.startServer();



    }

    public void startServer()
    {
        try {
            ServerSocket serverSocket=new ServerSocket(9999);
            while(true)
            {
                socket= serverSocket.accept();//阻塞程序
                System.out.println("服务器启动成功");
                sockets.add(socket);
                System.out.println("有客户端连接上了,客户端连接数为:"+sockets.size());
                //为每一个连接到服务器的客户端开启一个线程
                new A(socket).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("启动服务器失败");
        }
    }

    //创造一个内部类监听各个客户端是否给服务器端发送消息
    class A extends Thread{
        DataInputStream dataInputStream;

        public A(Socket socket) throws IOException {
            dataInputStream=new DataInputStream(socket.getInputStream());
        }

        @Override
        public void run() {
            while (true){//一直厮混换,监听客户端发送的消息
                try {
                    String msg=dataInputStream.readUTF();
                    jTextArea.append(msg+"\n");
                    //向不同的客户端转发消息
                    for(Socket s:sockets)
                    {
                        DataOutputStream dOut=new DataOutputStream(s.getOutputStream());
                        dOut.writeUTF(msg);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    System.out.println("一位客户端下线了");
                    sockets.remove(socket);
                    break;
                }
            }
        }
    }
}

 

启动服务器
public class serverRun {
    public static void main(String[] args) {
        new server();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/235279.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

logback的使用

1 logback概述 SLF4J的日志实现组件关系图如下所示。 SLF4J&#xff0c;即Java中的简单日志门面&#xff08;Simple Logging Facade for Java&#xff09;&#xff0c;它为各种日志框架提供简单的抽象接口。 SLF4J最常用的日志实现框架是&#xff1a;log4j、logback。一般有s…

LVS 三种负载均衡模式

昨天看视频了解LVS 三种负载均衡模式 &#xff0c;分别是Network Address Translation、Direct Routing、Tunneling 注&#xff1a;boardmix boardmix博思白板&#xff0c;多人实时协作的流程图&#xff0c;思维导图工具 https://boardmix.cn/ 画流程图还是很方便的

SSL 数字证书的一些细节

参考&#xff1a;TLS/SSL 协议详解(6) SSL 数字证书的一些细节1 证书验证 地址&#xff1a;https://wonderful.blog.csdn.net/article/details/77867063 参考&#xff1a;TLS/SSL协议详解 (7) SSL 数字证书的一些细节2 地址&#xff1a;https://wonderful.blog.csdn.net/articl…

Mybatis之核心配置文件详解、默认类型别名、Mybatis获取参数值的两种方式

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

聚类算法的性能度量

聚类算法的性能度量 聚类算法就是根据数据中样本与样本之间的距离或相似度&#xff0c;将样本划分为若干组&#xff0f;类&#xff0f;簇&#xff0c;其划分的原则&#xff1a;簇内样本相似、簇间样本不相似&#xff0c;聚类的结果是产生一个簇的集合。 其划分方式主要分为两…

[GWCTF 2019]我有一个数据库1

提示 信息收集phpmyadmin的版本漏洞 这里看起来不像是加密应该是编码错误 这里访问robots.txt 直接把phpinfo.php放出来了 这里能看到它所有的信息 这里并没有能找到可控点 用dirsearch扫了一遍 ####注意扫描buuctf的题需要控制扫描速度&#xff0c;每一秒只能扫10个多一个都…

基于深度学习的超分辨率图像技术一览

超分辨率(Super-Resolution)即通过硬件或软件的方法提高原有图像的分辨率&#xff0c;图像超分辨率是计算机视觉和图像处理领域一个非常重要的研究问题&#xff0c;在医疗图像分析、生物特征识别、视频监控与安全等实际场景中有着广泛的应用。 SR取得了显著进步。一般可以将现有…

网络设备的健康检查方式

网络设备的健康检查方式 L3检查 通过ICMP来检查IP地址是否正常 L4检查 通过三次握手来检查端口号是否正常 L7检查 通过真实的应用通信来检查应用程序是否正常

【CCF BDCI 2023】多模态多方对话场景下的发言人识别 Baseline 0.71 CNN 部分

【CCF BDCI 2023】多模态多方对话场景下的发言人识别 Baseline 0.71 CNN 部分 概述CNN 简介数据预处理查看数据格式加载数据集 图像处理限定图像范围图像转换加载数据 CNN 模型Inception 网络ResNet 残差网络总结参数设置 训练 Train模型初始化数据加载训练超参数训练循环 验证…

实现Django Models的数据mock

目录 一、创建测试数据 二、使用随机数据 三、使用第三方库生成数据 四、编写测试用例 五、总结 在 Django 中&#xff0c;Model 是用于定义数据库表的结构的类。有时候&#xff0c;我们需要在测试或者开发过程中&#xff0c;模拟 Model 的数据&#xff0c;而不是直接从数…

springboot基础(80):redis geospatial的应用

文章目录 前言redis geospatial如何从地图上获取经纬度springboot 的相关方法调用准备redis服务器引用的依赖预设位置的keyGEOADD 添加位置GEORADIUS 获取指定经纬度附件的停车场&#xff08;deprecated&#xff09;GEORADIUS 获取指定成员附件的停车场&#xff08;deprecated&…

SLMi8230BDCG-DG兼容Si8230BD-BS-IS 通过CQC认证隔离驱动方案探索

SLMi8230BDCG-DG 双通道1A 5.0kVRMS隔离栅极驱动器是一种具有不同配置的隔离双通道栅极驱动器。配置为高侧/低侧驱动器&#xff0c;峰值 电源 输出电流为1.0A&#xff0c;具有可编程死区&#xff08;DT&#xff09;功能。将DIS引脚拉高会同时关闭两个输出&#xff0c;并允许在D…

多合一iPhone 解锁工具:iMyFone LockWiper iOS

多合一iPhone 解锁工具 无需密码解锁 iPhone/iPad/iPod touch 上所有类型的屏幕锁定 在几分钟内解锁 iPhone Apple ID、Touch ID 和 Face ID 立即绕过 MDM 并删除 iPhone/iPad/iPod touch 上的 MDM 配置文件 支持所有 iOS 版本和设备&#xff0c;包括最新的 iOS 17 和 iPhone 1…

XML学习及应用

介绍XML语法及应用 1.XML基础知识1.1什么是XML语言1.2 XML 和 HTML 之间的差异1.3 XML 用途 2.XML语法2.1基础语法2.2XML元素2.3 XML属性2.4XML命名空间 3.XML验证3.1xml语法验证3.2自定义验证3.2.1 XML DTD3.2.2 XML Schema3.2.3PCDATA和CDATA区别3.2.4 参考 1.XML基础知识 1…

python:五种算法(DBO、WOA、GWO、PSO、GA)求解23个测试函数(python代码)

一、五种算法简介 1、蜣螂优化算法DBO 2、鲸鱼优化算法WOA 3、灰狼优化算法GWO 4、粒子群优化算法PSO 5、遗传算法GA 二、5种算法求解23个函数 &#xff08;1&#xff09;23个函数简介 参考文献&#xff1a; [1] Yao X, Liu Y, Lin G M. Evolutionary programming made…

[java学习日记]反射、动态代理

目录 一.反射的简单解释与获取字节码文件对象 二.获取构造方法对象Constructor 三.反射获取字节码文件中的成员变量Field 四.反射获取字节码文件中的成员方法&#xff1a;Method 五.反射练习&#xff1a;保存信息 六.反射练习&#xff1a;利用配置文件&#xff08;存储类名…

学习通【劳动通论】2023章节练习题

社会主义核心价值观24个字是&#xff1a;富强、民主、文明、和谐&#xff0c;自由、平等、公正、法治&#xff0c;爱国、敬业、诚信、友善。 1、“富强、民主、文明、和谐”&#xff0c;是我国社会主义现代化国家的建设目标&#xff0c;也是从价值目标层面对社会主义核心价值观…

超级实用的防止商品超卖的 7 种实现方式,非常好用!

高并发场景在现场的日常工作中很常见&#xff0c;特别是在互联网公司中&#xff0c;这篇文章就来通过秒杀商品来模拟高并发的场景。 本文环境&#xff1a; SpringBoot 2.5.7 MySQL 8.0 X MybatisPlus Swagger2.9.2 模拟工具&#xff1a; Jmeter 模拟场景&#xff1a; 减库…

2000字总结—Redis常见命令

与其明天开始&#xff0c;不如现在行动&#xff01; 文章目录 Redis常见命令通用命令String类型key的层级格式Hash类型List类型Set类型SortedSet类型 &#x1f48e;总结 Redis常见命令 通用命令 通过help[command]可以查看一个命令的具体用法 127.0.0.1:6379> help keysK…

鸿蒙应用开发ArkTS容器组件的使用

语雀知识库地址&#xff1a;语雀HarmonyOS知识库 飞书知识库地址&#xff1a;飞书HarmonyOS知识库 本文示例代码地址&#xff1a;Gitee 仓库地址 嗨&#xff0c;大家好&#xff0c;我是小白 上篇文章向大家介绍了 ArkTS 中我们经常使用到的几种基础组件&#xff0c;Text、Butt…