Java实现TCP一对一通信,实现UDP群聊通信

TCP一对一通信:

实现服务端对话框:

其中可自由更改对话框的样式


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地址和端口号进行链接:


import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
public class QqFu extends JFrame implements ActionListener{
    public static void main(String[] args){
        new QqFu();
    }
    // 说明:一个类需要页面的显示,则那个类要继承JFrame。
    // 属性
    // 文本域
    private JTextArea jta;
    // 滚动条
    private JScrollPane jsp;
    // 面板里面是文本框和按钮
    private JPanel jp;
    private JTextField jtf;
    private JButton jb ;
 
    BufferedWriter bw = null;
 
    // 构造器
    public QqFu(){
 
        // 初始化上面的属性
        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);
        jb.addActionListener(this);
 
        // 回车点击事件
 
        jtf.addKeyListener(new KeyAdapter() {
            public void keyTyped(KeyEvent e) {
                if((char)e.getKeyChar()==KeyEvent.VK_ENTER) {
                    useVoid01();
                }
            }
        });
 
 
 
        try{
            /*******客户端 TCP协议*********/
            // 1.创建一个客户端的套接字(尝试连接)
            Socket socket = new Socket("127.0.0.1",8888);
            // 2.获取socket通道的输入流
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            // 3
            bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            String line = null;
            while((line = br.readLine()) !=null){
                jta.append(line + "\n");
            }
            // 3. 获取输出流
 
            // 4.关闭流
            socket.close();
 
            /******************************/
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    public void actionPerformed(ActionEvent e){
        useVoid01();
    }
 
    public void useVoid01(){
        // 1.获取文本框中需要发送的内容
        String text = jtf.getText();
        // 2. 拼接内容
        text = "客户端对服务端说:" + text;
        // 3.自己显示
        jta.append(text + "\n");
        try{
            // 4.发送
            bw.write(text);
            bw.newLine(); // 换行
            bw.flush();  // 刷新
            // 5.清空
            jtf.setText("");
 
        }catch(IOException e1){
            e1.printStackTrace();
        }
    }
    //行为
}

必须先启动服务端再启动客户端才可,如果是两台电脑的情况下,只需要获得其中一个电脑的ip进行服务器启动,另一个进行链接即可。就可实现实时对话

效果展示:

UDP群聊服务器端:


 
import java.io.*;  
import java.net.*;  
import java.util.HashMap;  
import java.util.Map;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.ThreadPoolExecutor;  
import javax.swing.*;
import java.awt.*;
 
public class UDPServer extends JFrame{      
 
    private JTextArea m_display=new JTextArea();
 
    private ServerSocket serverSocket;  
 
    /** 
    * 创建线程池来管理客户端的连接线程 
    * 避免系统资源过度浪费 
    */  
    private ExecutorService exec;  
 
    // 存放客户端之间私聊的信息  
    private Map<String,PrintWriter> storeInfo;  
 
    public UDPServer() {  
        super("聊天程序服务器端");
        Container c=getContentPane();
        c.add(new JScrollPane(m_display),BorderLayout.CENTER);
        try {  
 
            serverSocket = new ServerSocket(6666);  
            storeInfo = new HashMap<String, PrintWriter>();  
            exec = Executors.newCachedThreadPool();  
 
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
 
    // 将客户端的信息以Map形式存入集合中  
    private void putIn(String key,PrintWriter value) {  
        synchronized(this) {  
            storeInfo.put(key, value);  
        }  
    }  
 
    // 将给定的输出流从共享集合中删除  
    private synchronized void remove(String  key) {  
        storeInfo.remove(key);  
        m_display.append("当前在线人数为:"+ storeInfo.size());
        //for(String name: storeInfo.key)
    }  
 
    // 将给定的消息转发给所有客户端  
    private synchronized void sendToAll(String message) {  
        for(PrintWriter out: storeInfo.values()) {  
            out.println(message);  
 
 
           // m_display.append("已经发送了");
        }  
    }  
 
    // 将给定的消息转发给私聊的客户端  
    private synchronized void sendToSomeone(String name,String message) {  
        PrintWriter pw = storeInfo.get(name); //将对应客户端的聊天信息取出作为私聊内容发送出去  
        if(pw != null) pw.println("私聊:     "+message);   
    }  
 
    public void start() {  
        try {  
            m_display.setVisible(true);
            //m_display.append("mayanshuo");
            while(true) { 
 
            m_display.append("等待客户端连接... ... \n"); 
 
            Socket socket = serverSocket.accept();  
 
            // 获取客户端的ip地址  
            InetAddress address = socket.getInetAddress();  
            m_display.append("客户端:“" + address.getHostAddress() + "”连接成功! ");  
            /* 
            * 启动一个线程,由线程来处理客户端的请求,这样可以再次监听 
            * 下一个客户端的连接 
            */  
            exec.execute(new ListenrClient(socket)); //通过线程池来分配线程  
            }  
        } catch(Exception e) {  
            e.printStackTrace();  
        }  
    }  
 
    /** 
    * 该线程体用来处理给定的某一个客户端的消息,循环接收客户端发送 
    * 的每一个字符串,并输出到控制台 
    */  
    class ListenrClient implements Runnable {  
 
        private Socket socket;  
        private String name;  
 
        public ListenrClient(Socket socket) {  
            this.socket = socket;  
        }  
 
        // 创建内部类来获取昵称  
        private String getName() throws Exception {  
            try {  
                //服务端的输入流读取客户端发送来的昵称输出流  
                BufferedReader bReader = new BufferedReader(  
                    new InputStreamReader(socket.getInputStream(), "UTF-8"));  
                //服务端将昵称验证结果通过自身的输出流发送给客户端  
                PrintWriter ipw = new PrintWriter(  
                    new OutputStreamWriter(socket.getOutputStream(), "UTF-8"),true);  
 
                //读取客户端发来的昵称  
                while(true) {  
                    String nameString = bReader.readLine();  
                    if ((nameString.trim().length() == 0) || storeInfo.containsKey(nameString)) {  
                        ipw.println("FAIL");  
                    } else {  
                        ipw.println("OK");  
                        return nameString;  
                    }  
                }  
            } catch(Exception e) {  
                throw e;  
            }  
        }  
 
        @Override         
        public void run() {  
            try {  
                /* 
                * 通过服务器端的socket分配给每一个 
                * 用来将消息发送给客户端 
                */  
                PrintWriter pw = new PrintWriter(  
                    new OutputStreamWriter(socket.getOutputStream(), "UTF-8"), true);  
 
                /* 
                * 将客户昵称和其所说的内容存入共享集合HashMap中 
                */  
                name = getName();  
                putIn(name, pw);  
                Thread.sleep(100);  
 
                // 服务端通知所有客户端,某用户上线  
                sendToAll("*系统消息* “" + name + "”已上线");  
 
                /* 
                * 通过客户端的Socket获取输入流 
                * 读取客户端发送来的信息 
                */  
                BufferedReader bReader = new BufferedReader(  
                    new InputStreamReader(socket.getInputStream(), "UTF-8"));  
                String msgString = null;  
 
 
                while((msgString = bReader.readLine()) != null) {  
                    // 检验是否为私聊(格式:@昵称:内容)  
                    if(msgString.startsWith("@")) {  
                        int index = msgString.indexOf(":");  
                        if(index >= 0) {  
                            //获取昵称  
                            String theName = msgString.substring(1, index);  
                            String info = msgString.substring(index+1, msgString.length());  
                            info =  name + ":"+ info;  
                            //将私聊信息发送出去  
                            sendToSomeone(theName, info);
 
                            sendToSomeone(name,info);
 
                            continue;  
                        }  
                    }  
                    // 遍历所有输出流,将该客户端发送的信息转发给所有客户端  
                    m_display.append(name+":"+ msgString+"\n");  
                    sendToAll(name+":"+ msgString);  
                }     
            } catch (Exception e) {  
                // e.printStackTrace();  
            } finally {  
                remove(name);  
                // 通知所有客户端,某某客户已经下线  
                sendToAll("*系统消息* "+name + "已经下线了。\n");  
 
                if(socket!=null) {  
                    try {  
                        socket.close();  
                    } catch(IOException e) {  
                        e.printStackTrace();  
                    }  
                }     
            }  
        }  
    }  
 
    public static void main(String[] args) {  
        UDPServer server = new UDPServer();
        server.setSize(400,400);
        server.setVisible(true);
        server.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        server.start();  
    }  
}  
 

UDP客户端:


import java.io.*;  
import java.net.*;  
import java.util.Scanner;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.ThreadPoolExecutor;  
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
 
public class UDPClient extends JFrame {  
 
    private JTextField m_enter=new JTextField();
    private JTextArea m_display=new JTextArea();
    private int m_count=0;
    private static  Socket clientSocket;  
    //private ExecutorService exec = Executors.newCachedThreadPool(); 
    private BufferedReader br;
    private PrintWriter pw;
 
    public UDPClient() 
    {
        super("聊天程序客户端");
 
 
        Container c=getContentPane();
        //m_enter.setSize(100,99);
        //m_display.setSize(200,100);
        m_enter.setVisible(true);
        m_display.setVisible(true);
        m_enter.requestFocusInWindow();     //转移输入焦点到输入区域
 
        //将光标放置在文本区域的尾部
        m_display.setCaretPosition(m_display.getText().length());
 
 
        c.add(m_enter,BorderLayout.SOUTH);
        c.add(new JScrollPane(m_display),BorderLayout.CENTER);  
        // this.add(panel);
        // this.setContentPane(jp);
 
    }  
 
 
    public static void main(String[] args) throws Exception {  
        UDPClient client = new UDPClient();
        client.setVisible(true);
        client.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        client.setSize(470,708);
        client.start();  
    }  
 
 
    public void start() {  
        try {  
            m_display.append("请创建用户名:");
            clientSocket=new Socket("localhost",6666);
            BufferedReader br = new BufferedReader(  
                    new InputStreamReader(clientSocket.getInputStream(), "UTF-8")); 
            PrintWriter pw = new PrintWriter(  
                    new OutputStreamWriter(clientSocket.getOutputStream(), "UTF-8"), true); 
            //ListenrServser l=new ListenrServser();
            m_enter.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent event)
                {
                    try{
                    String s=event.getActionCommand();
                    m_enter.setText("");
                     if(m_count==0)
                    {
                         pw.println(s);
                         m_display.append("\n'"+s+"'"+"昵称设置成功。\n");
 
                    }
                    else
                    {
 
                            pw.println(s);
 
                    }
                    m_count++;
 
                    }catch(Exception e)
                    {
                        e.printStackTrace();
                    }
                }
            });
 
 
            String msgString;
            while((msgString = br.readLine())!= null) {  
                m_display.append(msgString+"\n");  
            }  
 
 
        } catch(Exception e) {  
            e.printStackTrace();  
        } finally {  
            if (clientSocket !=null) {  
                try {  
                    clientSocket.close();  
                } catch(IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
    }  
 
 
 
}

运行结果:

1、这里是服务器端,显示当前连接人数,以及公聊信息:

自由创建对象来实现群聊

效果如图:

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

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

相关文章

可视化监控/安防视频云平台公共区域人员行为安全监控方案

大家在浏览新闻时&#xff0c;经常会看到某某地区有人员摔倒&#xff0c;长时间无人发现或人员闯入某危险区域管理人员未及时劝离&#xff0c;导致发生了意外事故的新闻。由于人力资源和人为巡检能力有限&#xff0c;在很多公共区域无法及时检测人员行为从而导致危险发生。为确…

千万别碰SLAM,会变得不幸--下阙

0.书接上回 之前的工作内容总结: 1.学习了回环检测的流程,还学习了DLoopDetector算法。 2.修改了vins-mono将匹配和回环到的图片进行保存。 3.找到了一个不是办法的办法来代替pr曲线,指定范围作真值。 4.大致了解了DTW地磁匹配算法,关键点是要划分第一圈和第二圈的界限。 …

如何还原分区? 分区和卷恢复的详细步骤

​我们曾介绍过用傲梅轻松备份将分区备份为镜像文件的方法。那备份好的分区如何恢复呢&#xff1f;同样&#xff0c;使用傲梅轻松备份也能实现分区的还原。以下是分区还原的步骤&#xff1a; 提示&#xff1a;提前使用傲梅轻松备份创建一个可启动U盘。 1. 准备U盘启动…

QT----自定义信号和槽

第二天 2.1自定义信号和槽 新建一个Qtclass 自定义信号&#xff1a;返回值是void &#xff0c;只需要声明&#xff0c;不需要实现&#xff0c;可以有参数&#xff0c;可以重载 自定义槽&#xff1a;返回值void &#xff0c;需要声明&#xff0c;也需要实现&#xff0c;可以有…

学习Opencv(蝴蝶书/C++)相关1——4.图形和大型数组类型

文章目录 1. 多维度数组和多通道数组区别2. NAryMatIterator详解2.1 介绍2.2 dispatch和SIMD(OpenCV和numpy)2.2.1 OpenCV的2.2.2 numpy的2.2.3 OpenCV文档搜索2.3 调用指令集对代码进行优化2.4 NAryMatIterator理解2.4.1 plane和连续2.4.2 构造函数和迭代2.5 NAryMatIterato…

快速认识什么是:Kubernetes

每次谈到容器的时候&#xff0c;除了Docker之外&#xff0c;都会说起 Kubernetes&#xff0c;那么什么是 Kubernetes呢&#xff1f;今天就来一起学快速入门一下 Kubernetes 吧&#xff01;希望本文对您有所帮助。 Kubernetes&#xff0c;一种用于管理和自动化云中容器化工作负…

从传统到胜利:广汽集团汽车产业创新之旅

置身于汽车行业百年未有之大变局&#xff0c;作为传统车企中的排头兵&#xff0c;广汽创新可圈可点&#xff0c;广汽近年来取得了骄人业绩&#xff0c;不论是整体产销规模&#xff0c;还是新能源汽车产业化、新技术领域开拓等&#xff0c;都呈现节节攀升的局面。本文奖从产业变…

【网络安全】零日漏洞(0day)是什么?如何防范零日攻击?

零日攻击是利用零日漏洞&#xff08;0day&#xff09;对系统或软件应用发动的网络攻击&#xff0c;近年来&#xff0c;零日攻击威胁在日益增长且难以防范&#xff0c;零日攻击已成为企业网络信息安全面临的最严峻的威胁之一。 文章目录 What is a zero-day attack&#xff1f;…

2023年12月8日历史上的今天大事件早读

1633年12月8日 明代科学家徐光启逝世 1794年12月8日 法国大革命吉伦派分子被接纳进法国国民大会 1813年12月8日 已丧失听觉的贝多芬指挥自己第七交响乐的首演音乐会 1856年12月8日 英国物理学家、电子发现者约瑟夫-约翰-汤姆逊出生 1920年12月8日 西北五马联合自治 1925年…

Python django-xadmin:构建强大的 Django 后台管理系统

概要 Django作为一款强大的Web框架&#xff0c;其后台管理系统提供了便捷的数据管理和操作方式。而 django-xadmin 则为Django的后台管理系统提供了更加强大的功能和灵活的定制选项。在本文中&#xff0c;我们将深入研究如何使用django-xadmin&#xff0c;并通过详细的示例代码…

0009Java程序设计-ssm微信小程序在慢性疾病管理中的应用

文章目录 **摘要**目录系统实现开发环境 编程技术交流、源码分享、模板分享、网课分享 企鹅&#x1f427;裙&#xff1a;776871563 摘要 首先,论文一开始便是清楚的论述了小程序的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例…

Navicat连接Oracle数据库

Navicat连接Oracle数据库 打开服务里面找到Oracle服务 OracleServerXE或者OracleServerTTL 创建数据库连接 连接名默认自己起 主机选择本地 端口默认 服务名在服务中可以找到输入后缀 用户名默认都是system 密码是创建oracle时候填写的口令 点击测试连接即可

老师如何管理课堂纪律?

在教学过程中&#xff0c;保持良好的课堂纪律是十分重要的&#xff0c;它能够保证教学质量、促进学生学习效果的提升和教师教学效率的提高。然而&#xff0c;如何有效地管理课堂纪律成为一个极为重要的问题。接下来&#xff0c;本文将介绍几种管理课堂纪律的方法。 1. 建立规章…

flutter添加全局水印

效果&#xff1a; 可以直接引用&#xff1a;disable_screenshots: ^0.2.0 但是有时候直接引用会报错&#xff0c;可以不引用插件直接把下面的源码工具类放在项目里面 工具类源码&#xff1a; import dart:io; import dart:math;import package:flutter/cupertino.dart; impor…

docker:搭建私有仓库

文章目录 1、拉取镜像2、运行容器3、测试成功4、修改daemon.json5、重启docker 服务6、上传镜像到私有仓库6.1 标记某个镜像为私有仓库镜像6.2 上传镜像到私有仓库 其他注意项 1、拉取镜像 docker pull registry2、运行容器 docker run -di --nameregistry -p 5000:5000 regi…

北京发布阅读分级指南 促进阅读素养提升

12月5日,《北京市中小学生阅读能力分级标准指南(试行)》发布。据悉,指南适用于义务教育阶段和高中阶段,共构建五级能力分级指标体系。旨在通过明确各学年段学生的阅读素养发展目标来指导学生进行分级阅读,从而淡化学科界限,突出学生在学习、生活中真实的阅读情境和阅读能力要求…

如何通过EDI向Daimler发送发票?

此前的文章&#xff1a;Daimler EDI 项目案例 中&#xff0c;我们已经成功对接Daimler&#xff0c;接下来我将为大家介绍如何将发票由Daimler的发票系统切换至EDI。 EDI需求背景 在Daimler的前期需求中&#xff0c;只涉及到了VDA4905交付预测以及VDA4913发货通知两种报文。对…

java版王者荣耀(源代码)

1.项目结构截图 2.源代码 2.1 backgroud package com.sxt;import javax.swing.*; import java.awt.*;public class Background extends GameObject {public Background(GameFrame gameFrame) {super(gameFrame);// TODO Auto-generated constructor stub}Image bg Toolkit.ge…

直方图均衡化实现

一 直方图均衡化的概念 直方图均衡化(Histogram Equalization)是一种**增强图像对比度**(Image Contrast)的方法&#xff0c;其主要思想是将一副图像的**灰度直方图分布**通过**累积分布函数**变成**近似均匀分布**&#xff08;直观上在某个灰阶范围内像素值保持一致 &#xf…

Linux信号量

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;Linux &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客主要内容感性认识了信号量&#xff0c;并且认识了IPC资源在操作…