Java 实现TCP一对一聊天,UDP协议实现群聊

用TCP编程实现一对一式聊天,并用多线程解决了处于同一线程中的问题。
客户端代码:mport java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
 
public class ChatSocketClient {
    public static void main(String[] args) {
 
        try {
            Socket socket =new Socket("127.0.0.1",8888);
            System.out.println("连接成功!");
            new ClientSend(socket).start();
            new Clientreive(socket).start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
/**
 * 用于发送消息线程类
 */
class ClientSend extends Thread{
    @Override
    public void run() {
        this.sendMsy();
    }
    private Socket socket;
    public ClientSend(Socket socket){
        this.socket  =socket;
    }
    /**
     * 发送消息
     */
    private void sendMsy(){
        Scanner scanner =null;
        PrintWriter pw =null;
        try{
            scanner =new Scanner(System.in);
            pw =new PrintWriter(this.socket.getOutputStream());
            while(true){
                String str =scanner.nextLine();
                pw.println(str);
                pw.flush();
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (scanner!=null){
                scanner.close();
            }
            if (pw!=null){
                pw.close();
            }
            if (socket!=null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
 
/**
 *用于接收消息线程类
 */
class Clientreive extends Thread{
    private Socket socket=null;
    public Clientreive(Socket socket){
        this.socket =socket;
    }
 
    @Override
    public void run() {
        this.receiveMsg();
    }
    /**
     * 用于接收对方消息
     */
    private void receiveMsg(){
        BufferedReader br =null;
        try{
            br =new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
            while(true){
                String mr = br.readLine();
                System.out.println("他说"+mr);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (br!=null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
 
        }
    }
}服务端代码: 
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.Scanner;
 
/**
 * 发送消息线程
 */
class Send extends Thread{
    private Socket socket;
    public Send(Socket socket){
        this.socket  =socket;
    }
    @Override
    public void run() {
        this.sendMsy();
    }
    /**
     * 发送消息
     */
    private void sendMsy(){
        Scanner scanner =null;
        PrintWriter pw =null;
        try{
            scanner =new Scanner(System.in);
            pw =new PrintWriter(this.socket.getOutputStream());
            while(true){
                String str =scanner.nextLine();
                pw.println(str);
                pw.flush();
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (scanner!=null){
                scanner.close();
            }
            if (pw!=null){
                pw.close();
            }
            if (socket!=null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
 
/**
 * 接收消息的线程
 */
class receive extends Thread{
    private Socket socket=null;
    public receive(Socket socket){
        this.socket =socket;
    }
 
    @Override
    public void run() {
        this.receiveMsg();
    }
    /**
     * 用于接收对方消息
     */
    private void receiveMsg(){
        BufferedReader br =null;
        try{
            br =new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
            while(true){
                String mr = br.readLine();
                System.out.println("他说"+mr);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (br!=null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
 
        }
    }
}
 
public class ChatSocketServer {
    public static void main(String[] args) {
        ServerSocket serverSocket =null;
        try{
            serverSocket =new ServerSocket(8888);
            System.out.println("服务端已启动等待连接");
            Socket socket = serverSocket.accept();
            System.out.println("连接成功!");
            new Send(socket).start();
            new receive(socket).start();
        }catch(Exception e){
            e.printStackTrace();
        }finally {
            if (serverSocket!=null){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

实现服务端对话框:
其中可自行更改对话框大小样式等配置。

 
  1. package com.ex.controller;
     
    import javax.servlet.http.HttpServletRequest;
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.io.*;
    import java.net.*;
    public class QqMain extends JFrame implements ActionListener{
        public static void main(String[] args){
     
            InetAddress ia = null;
            try {
                ia = ia.getLocalHost();
                String localip = ia.getHostAddress();
                System.out.println("本机的ip是 :" + localip);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            new QqMain();
        }
     
     
        // 说明:一个类需要页面的显示,则那个类要继承JFrame。
        // 属性
        // 文本域
        private JTextArea jta;
        // 滚动条
        private JScrollPane jsp;
        // 面板里面是文本框和按钮
        private JPanel jp;
        private JTextField jtf;
        private JButton jb ;
     
        BufferedWriter bw  = null;
     
        // 构造器
        public QqMain(){
     
            // 初始化上面的属性
            jta = new JTextArea();
     
            // 将文本域添加到滚动条中
            jsp = new JScrollPane(jta);
            jp = new JPanel();
            jtf =new JTextField(15);
            jb = new JButton("发送");
     
            // 把按钮和文本框添加到面板中
            jp.add(jtf);
            jp.add(jb);
     
            // 把滚动条和面板添加到JFrame中去
            this.add(jsp,BorderLayout.CENTER); //这个设置在中间
            this.add(jp,BorderLayout.SOUTH); //南
     
            this.setTitle("qq聊天");
            this.setSize(500,500);
            this.setLocation(200, 200);
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.setVisible(true);
     
            /***********TCP协议*************/
            jb.addActionListener(this);  // 这是按钮点击使用
            // 回车键的监听事件 在接口KeyListener中
            //jtf.addKeyListener(this);
     
     
            jtf.addKeyListener(new KeyAdapter() {
                public void keyTyped(KeyEvent e) {
                    if((char)e.getKeyChar()==KeyEvent.VK_ENTER) {
                        useVoid();
                    }
                }
            });
     
            try{
                // 1.创建一个服务端的套接字
                ServerSocket serverSocket = new ServerSocket(8888);
     
                //2.等待客户端的连接
                Socket socket = serverSocket.accept();
     
                // 3.获取socket通道的输入流(输入流的读取方式为一行一行的读取方式 ----> readLine())
                BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
     
                // 4.获取通道的输入流(也是一行一行的写出  BufferedWriter ->newLine())
                // 当用户点击“发送”按钮的时候才会,写出数据
                bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                String line = null;
                while((line = br.readLine()) !=null){
                    // 将读取的数据拼接到文本域中显示
                    jta.append(line + "\n");
                }
     
     
                // 5.关闭socket通道
                serverSocket.close();
     
            }catch(IOException e){
                e.printStackTrace();
            }
     
            /************************/
     
     
        }
        // 点击按钮所实现的方法
        public void actionPerformed(ActionEvent e){
            useVoid();
        }
     
        public void useVoid(){
            // 1.获取文本框中的内容
            String text = jtf.getText();
            text = "服务端对客户端说:" + text;
            // 自己显示
            jta.append(text + "\n");
            // 2.发送
            try{
                // 4.发送
                bw.write(text);
                bw.newLine(); // 换行
                bw.flush();  // 刷新
                // 5.清空文本框
                jtf.setText("");
            }catch (IOException e1){
                e1.printStackTrace();
            }
        }
     
     
        /*public void KeyPressed(KeyEvent e){
            //回车键
            System.out.println("按钮数字");
        }
        public void KeyTyped(KeyEvent e){
        }
        public void KeyReleased(KeyEvent e){
        }*/
        //行为
    }必须先启动服务端再启动客户端才可,如果是两台电脑的情况下,只需要获得其中一个电脑的ip进行服务器启动,另一个进行链接即可。就可实现实时对话
    效果展示:服务器端:
    1.1 服务器端继承JFrame框架,添加组件。
    1.2 创建服务器端socket。建立一个哈希表,用于存储客户端的昵称以及服务器端对于每个连接的客户端建立的输出流。
    1.3建立一个线程池,为每个连接的客户端分配一个执行线程。
    1.3调用服务器端Socket的accept()函数,等待客户端的连接,每连接到一个客户端,线程池给相应的客户端分配一个线程。\n1.4每个线程内,调用服务器端Socket,封装getOutputStream(),获得服务器端Socket相对应于连接的客户端的输出流和输入流。输入流首先读取到客户端发送来的昵称。将客户端的昵称和服务器端的输出流存储在哈希表中,并遍历整个哈希表,将某人上线的通知发送给所有的在线客户端。
    1.5客户端将信息发送给服务器端,当服务器端传来的信息符合“@私聊对象:私聊信息”的格式时,服务器端认为这是私聊信息。服务器端将把私聊对象的昵称从信息中提取出来,通过哈希表找到与昵称对应的输出流。将私聊信息通过输出流发送给私聊对象。
    当不是私聊信息时,服务器遍历整个哈希表,通过每个客户端对应的输出流发送给每个客户端。
    1.6当客户端下线时,服务器端将移除哈希表中对应存储的客户端昵称以及输出流。并通知在线的每个客户端,某人已下线。
    (二) 客户端:
    2.1 客户端继承框架JFrame,添加各种组件。
    2.2 创建客户端Socket,设置请求连接服务器端IP,以及使用的端口号。
    2.3 封装客户端Socket的getInputStream()函数,获得客户端Socket的输入流接受服务器端发来的信息,封装Socket的getOutputStream()函数,获得Socket的输出流向服务器端发送信息。
    2.4 通过向文本框添加动作事件监听器,监听文本框的输入。
    2.5 当与服务器端连接成功时,系统提醒输入昵称。系统将对输入的昵称进行检索。判断是否有重复的昵称。如有重复则创建不成功,继续输入。
    2.6 向服务器端发送信息时,如想对某人发送私聊信息,则需输入符合“@私聊对象的呢称:私聊信息”的格式,此时只有私聊对象和本人可以接收到。否则,发送的信息为公聊信息,所有的客户端都能够收到。
    2.7 客户端不断接受服务器端的信息显示在文本域。

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

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

相关文章

c++ - 警告 : treating ‘c-header‘ input as ‘c++-header‘ when in C++ mode, 此行为已弃用

一、问题出现 在进行多文件编译的时候报错 二、原因 我们多文件编译的时候加了头文件 三、解决办法 去掉头文件,只编译源文件

流星雨效果

文章目录 html css实现jscanvas实现 html css实现 对于 HTML 来说,:root 表示 元素,除了优先级更高之外,与 html 选择器相同。带有前缀 – 的属性名,比如 --example–name,表示的是带有值的自定义属性,其…

Threejs项目实战之一:汽车外观换肤效果三维展示

目录 最终效果1 创建项目2 安装插件3 编写代码3.1 准备工作3.2 代码编写3.2.1 在template标签中构建html页面3.2.2 在style标签中构建页面样式文件3.2.3 在script标签中编写js代码 最终效果 先看下最终实现的效果 接下来,我们就从创建项目开始,一步一步…

ChatGPT/GPT4科研实践篇: AI绘图+论文写作+编程

1、熟练掌握ChatGPT提示词技巧及各种应用方法,并成为工作中的助手。 2、通过案例掌握ChatGPT撰写、修改论文及工作报告,提供写作能力及优化工作 3、熟练掌握ChatGPT融合相关插件的应用,完成数据分析、编程以及深度学习等相关科研项目。 4、…

【Windows本地端口占用脚本自动化】

本地启动多个Java微服务,因为停电或者内存回收原因,IDEA直接退出;再次启动各个服务会提示端口占用。 每次都cmd输入命令手动Kill比较繁琐,可以把此脚本放在桌面上作为一个小工具,运行即可。 代码(核心部分是chatGPT自…

k8s中的Pod网络;Service网络;网络插件Calico

Pod网络;Service网络;网络插件Calico Pod网络 在K8S集群里,多个节点上的Pod相互通信,要通过网络插件来完成,比如Calico网络插件。 使用kubeadm初始化K8S集群时,有指定一个参数–pod-network-cidr10.18.0…

【react】动态页面转换成html文件下载,解决样式问题

需求 今天遇到一个需求,挺恶心人的,将一个在线文档页面,可以导出成为html页面查看。 看到网上有使用fs模块,通过react的ReactDOMServer.renderToStaticMarkup将组件转成html字符串,输出文件了。 但是我尝试了&#x…

返回列表中满足指定条件的连续元素:只返回第一个不符合条件元素之前的各元素itertools.takewhile()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 返回列表中满足指定条件的连续元素: 只返回第一个不符合条件元素之前的各元素 itertools.takewhile() [太阳]选择题 请问以下代码输出的结果是? import itertools a …

在VSCode中运行Python脚本文件时如何传参

以下实验所处的操作系统环境说明: OS版本MacOSMonterey 12.1VSCodeOctober 2023 (version 1.84.2) 一、背景 在 VSCode 中写好 Python 脚本后,如果要运行起来,可以怎么做呢? 一般有以下几种方式: 1、直接在 VSCode…

【ARM Trace32(劳特巴赫) 使用介绍 11 -- Trace32 ARMv8/v9 系统寄存器读写】

文章目录 Trace32 ARMv8/v9 系统寄存器读写 Trace32 ARMv8/v9 系统寄存器读写 本文主要介绍如何使用trace32 来对 ARMv8 的系统寄存器及debug 寄存器进行配置,具体配置方法如下: 步骤1: 步骤2: 步骤3: 步骤4&#xf…

商务与经济统计案例分析:3-1Pelican 商店——python 实现

商务与经济统计案例分析:3-1Pelican 商店 要求Python实现 要求 1.净销售额的描述统计量和各种不同类型顾客的净销售额的描述统计量。 2.关于年龄与净销售额之间关系的描述统计量。 Python实现 0.相关分析:2-1案例 1.净销售额的描述统计量和各种不同类型顾客的净销…

【Docker二】docker网络模式、网络通信、数据管理

目录 一、docker网络模式: 1、概述 2、docker网络实现原理: 3、docker的网络模式: 3.1、bridge模式: 3.2、host模式: 3.3、container模式: 3.4、none模式: 3.5、自定义网络模式&#xf…

stateflow——如何查看状态机中参数变化及状态机断点调试

法一:使用Data Inspector 点击“符号图窗”和“属性”,如图;在选择变量n并右键点击inspector,最后在logging,如图 法二:log active state 和法一类似使用data inspector查看,类似的查看方法和…

《机器学习实战》MNIST 数据集的导入方法

1、在网上下载数据集 mnister 数据集有两个类型, (1)一个是手写的阿拉伯数字图片:MNIST 下载地址: 链接:https://pan.baidu.com/s/1dd-I-laysPbT8wxbyvxTvg 提取码:1234 (2…

【Flink系列五】Checkpoint及Barrier原理

本章内容 一致性检查点从检查点恢复状态检查点实现算法-barrier保存点Savepoint状态后端(state backend) 本文先设置一个前提,流处理的数据都是可回放的(可以理解成消费的kafka的数据) 一致性检查点(che…

基于ssm少儿编程管理系统源码和论文

idea 数据库mysql5.7 数据库链接工具:navcat,小海豚等 环境: jdk8 tomcat8.5 开发技术 ssm 基于ssm少儿编程管理系统源码和论文744 摘要 网络的广泛应用给生活带来了十分的便利。所以把少儿编程管理系统与现在网络相结合,利用java技术建设…

安装python第三方库后,在pycharm中不能正常导入

python小白学习opencv,使用pip安装完opencv库后import cv2报错,按照如下设置解决: 需要正确设置python解释器路径

VC++使用GetProcessTimes获取进程创建时间、销毁时间、用户态时间、内核态时间

一、GetProcessTimes函数简介(微软MSDN) 微软提供了一个非常有用的API函数GetProcessTimes用来获取进程创建时间、销毁时间、用户态时间、内核态时间,msdn连接为:GetProcessTimes 函数 (processthreadsapi.h) 其函数原型为&#…

<Linux>(极简关键、省时省力)《Linux操作系统原理分析之Linux文件管理(3)》(27)

《Linux操作系统原理分析之Linux文件管理(3)》(27) 8 Linux文件管理8.6 文件管理和操作8.6.1 系统对文件的管理8.6.2 进程对文件的管理 8 Linux文件管理 8.6 文件管理和操作 8.6.1 系统对文件的管理 Linux 系统把所有打开的活动…

智能优化算法应用:基于北方苍鹰算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于北方苍鹰算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于北方苍鹰算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.北方苍鹰算法4.实验参数设定5.算法结果6.参考…