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 blocke.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()));// 3bw = 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、这里是服务器端,显示当前连接人数,以及公聊信息:
自由创建对象来实现群聊
效果如图:
相关文章:

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 …...

Vue + Element 实现按钮指定间隔时间点击
1、业务需求 需要加一个按钮,调用第三方API,按钮十分钟之内只能点击一次,刷新页面也只能点击一次 2、思路 加一个本地缓存的时间戳,通过时间戳计算指定时间内不能点击按钮 3、实现 1)vue页面 <template>&l…...

UE Websocket笔记
参考链接 [UE4 C入门到进阶]12.Websocket网络通信 - 哔哩哔哩 包含怎么用Nodejs 写测试服务器 UE4_使用WebSocket和Json(上) - 知乎 包含Python写测试服务器 UE4_使用WebSocket和Json(下) - 知乎 示例代码 xxx.Build.cs"W…...
STM32h7 接收各种can id情况下滤波器的配置
1、接收所有数据 /* 此处id2都为0,不进行id校验,接收所有数据*/ static void CAN_Filter_Config(void){FDCAN_FilterTypeDef sFilterConfig1;/* Configure Rx filter */sFilterConfig1.IdType FDCAN_STANDARD_ID;sFilterConfig1.FilterIndex 0;sFilte…...

《深入理解计算机系统》学习笔记 - 第三课 - 浮点数
Floating Point 浮点数 文章目录 Floating Point 浮点数分数二进制示例能代表的数浮点数的表示方式浮点数编码规格化值规格化值编码示例 非规格化的值特殊值 示例IEEE 编码的一些特殊属性四舍五入,相加,相乘四舍五入四舍五入的模式二进制数的四舍五入 浮…...
总结:服务器批量处理http请求的大致流程
总结:服务器批量处理http请求的大致流程 一客户端发起请求:可以多个请求同时发送二Web服务器解析请求(如:Nginx):可以多个请求同时解析三Servlet容器接收请求(如:tomcat)…...

算法通关村第十八关-青铜挑战回溯是怎么回事
大家好我是苏麟 , 今天聊聊回溯是怎么个事 . 回溯是最重要的算法思想之一,主要解决一些暴力枚举也搞不定的问题,例如组合、分割、子集、排列,棋盘等。从性能角度来看回溯算法的效率并不高,但对于这些暴力都搞不定的算法能出结果就…...

区分node,npm,nvm
目录 一,nodejs二,npm三,nvm 区分node,npm,nvm 几年前学习前端的时候学习的就是htmlcssjs 三件套。 现在只学习这些已经不能满足需要了。 一,nodejs nodejs是编程语言javascript运行时环境。(比…...
7-2 小霸王
幼儿园的老师给几位小朋友等量的长方体橡皮泥,但有个小朋友(小霸王)觉得自己的橡皮泥少了,就从另一个小朋友那里抢了一些。请问,是哪个小霸王抢了哪个小朋友的橡皮泥? 输入格式: 测试数据有多组。对于每组…...

Linux内核上游提交完整流程及示例
参考博客文章: 向linux内核提交代码 - 知乎 一、下载Linux内核源码 通过git下载Linux内核源码,具体命令如下: git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 实际命令及结果如下: penghaoDin…...
TS学习——快速入门
TypeScript简介 TypeScript是JavaScript的超集。它对JS进行了扩展,向JS中引入了类型的概念,并添加了许多新的特性。TS代码需要通过编译器编译为JS,然后再交由JS解析器执行。TS完全兼容JS,换言之,任何的JS代码都可以直…...

深圳锐科达风力发电广播对讲解决方案
深圳锐科达风力发电广播对讲解决方案 风力发电对讲通常是在风塔的底部与机舱室安装一键对讲终端,可以一键呼叫控制中心值班人员,结构简单,组网方便,设备可以接入局域网或广域网构成功能应急呼叫系统。 系统实现的功能࿱…...
极智芯 | 解读国产AI算力 璧仞产品矩阵
欢迎关注我,获取我的更多经验分享 大家好,我是极智视界,本文分享一下 解读国产AI算力 璧仞产品矩阵。 璧仞在国产 AI 芯领域就是 "迷" 一样的存在,你要说它在市场上的 "建树" 泛善可陈的话,它又 "赫然" 在美国芯片禁令名单中。而这一切的一…...
Echarts折线图常见问题及案例代码
前言 ECharts 是一个使用 JavaScript 实现的开源可视化库,它可以帮助用户以简单的方式创建复杂的时间序列、条形图、饼图、地图等图形。 初学者,可参考下我的另外两篇文章,从基础到深入,解读饼状图的运用。 ECharts初始案例(入门) ECharts之折线图 常见问题及案例代码 …...

javaTCP协议实现一对一聊天
我们首先要完成服务端,不然出错,运行也要先运行服务端,如果不先连接服务端,就不监听,那客户端不知道连接谁 服务端 package d21z; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.a…...

机器学习应用 | 使用 MATLAB 进行异常检测(上)
异常检测任务,指的是检测偏离期望行为的事件或模式,可以是简单地检测数值型数据中,是否存在远超出正常取值范围的离群值,也可以是借助相对复杂的机器学习算法识别数据中隐藏的异常模式。 在不同行业中,异常检测的典型…...
Java -jar参数详解
java -jar 命令用于执行打包成可执行 JAR 文件的 Java 应用程序。在运行时,你可以通过命令行传递参数给这个应用程序。 1. -jar 参数: 说明: 指定要执行的 JAR 文件。示例:java -jar your-application.jar 2. -D 参数ÿ…...

RocksDB 在 vivo 消息推送系统中的实践
作者:vivo 互联网服务器团队 - Zeng Luobin 本文主要介绍了 RocksDB 的基础原理,并阐述了 RocksDB 在vivo消息推送系统中的一些实践,通过分享一些对 RocksDB 原生能力的探索,希望可以给使用RocksDB的读者带来启发。 一、背景 在…...

【C进阶】C程序是怎么运作的呢?-- 程序环境和预处理(上)
前言: 由于c语言的程序编译链接的这块知识点不清楚,回来复习一遍,以便于好理解c知识,我会尽快更新下一篇文章。 目录 1.程序的翻译环境和执行环境 2.翻译环境(编译链接) 编译(编译器…...

点滴生活记录1
2023/10/10 今天骑小电驴上班,带着小鸭子一起。路上的时候,我给小鸭子说,你要帮我看着点路,有危险的时候提醒我,也就刚说完没几分钟,一个没注意,直接撞到一个拦路铁墩子上,车子连人歪…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...

Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...
从实验室到产业:IndexTTS 在六大核心场景的落地实践
一、内容创作:重构数字内容生产范式 在短视频创作领域,IndexTTS 的语音克隆技术彻底改变了配音流程。B 站 UP 主通过 5 秒参考音频即可克隆出郭老师音色,生成的 “各位吴彦祖们大家好” 语音相似度达 97%,单条视频播放量突破百万…...