当前位置: 首页 > news >正文

Java Socket Server TCP服务端向指定客户端发送消息

实现思路
首先需要知道java里如何创建一个Socket服务器端。

    //创建一个服务器端对象ServerSocket server = new ServerSocket(); //绑定启动的ip和端口号server.bind(new InetSocketAddress("127.0.0.1",8082));//启动成功后,调用accept()方法阻塞,//当有客户端成功连接时会生成一个Socket对象用于通讯Socket socket = server.accept();


提示:注意server.accept()方法调用会阻塞,只有新的客户端连接后才返回一个新的socket对象。如果一直未连接那么会一直处于阻塞状态

1、了解了如何创建一个socket服务器端后。那么如何实现给指定的连接客户端发送消息呢?首先我们可以知道只有有客户端连接服务器就会生成一个socket对象,socket对象中获取对应的输入输出流读取和写入就可以实现发送消息;也就是只要咱们把每次连接的socket保存起来,发送和接收数据就直接获取对应的socket就可以实现。
2、总结一下。也就是需要循环调用 server.accept()阻塞方法,对每个连接的socket保存起来。并对每一个socket实现读取写入操作。为了可用性。对于服务器阻塞方法需要单独创建一个线程进行阻塞等待连接操作。并且对于每一个连接的客户端单独创建一个线程进行读写操作。
好了话不多说直接上代码

项目源码
服务器端接口ISocketServer

/*** @description: 启用socket服务* @author * @date 2024/2/19 13:51* @version 1.0*/
public interface ISocketServer {/*** @description: 启动服务* @author liangxuelong* @date 2023/6/19 13:53* @version 1.0*/public void startServer();/*** @description: 停止服务* @author liangxuelong* @date 2023/6/19 13:53* @version 1.0*/public void stopServer();/*** @description: 判断是否启动* @author liangxuelong* @date 2023/6/19 14:01* @version 1.0*/public boolean isStart();}


服务器端实现一个抽象类AbstractSocketServer,定义启动、停止。查看连接状态等方法

/*** @author ** @version 1.0* @description:* @date 2023/6/19 14:04*/
public abstract class AbstractSocketServer implements ISocketServer{//服务器端口protected int port;//默认ip地址protected String ipAddress = "127.0.0.1";//默认最大连接数protected int maxConnectSize = 1;//当前连接状态protected boolean isConn = false;//java ServerSocket 对象private ServerSocket server;//保存所有连接通讯类protected ConcurrentHashMap<String,ICommunication> communications = new ConcurrentHashMap<>();public AbstractSocketServer(String ipAddress, int port) {this.ipAddress = ipAddress;this.port = port;}public AbstractSocketServer(int port) {this.port = port;}/*** @description: 启动服务* @author liangxuelong* @date 2023/6/19 16:14* @version 1.0*/@Overridepublic void startServer() {new Thread(() -> {try {if (isConn) {stopServer();}server = new ServerSocket();//绑定数据连接地址端口号server.bind(new InetSocketAddress(ipAddress,port));//绑定成功设置当前服务器状态为trueisConn = true;//循环等待客户端连接while(true){//阻塞 等待socket client 连接Socket socket = server.accept();//生成连接通讯对象SocketCommunication socketCommunication = new SocketCommunication(socket,this);new Thread(() -> {try {addCommunication(socketCommunication);socketCommunication.handle();} catch (Exception e) {e.printStackTrace();}removeCommunication(socket.getInetAddress().getHostAddress());}).start();}} catch (IOException ioException) {ioException.printStackTrace();}}).start();}/*** @description: 停止服务* @author liangxuelong* @date 2023/6/19 16:14* @version 1.0*/@Overridepublic void stopServer(){if (server != null) {try {server.close();} catch (IOException ioException) {ioException.printStackTrace();}isConn = false;removeAllCommunication();}}/*** @description: 给所有连接发送* @author liangxuelong* @date 2023/6/19 16:51* @version 1.0*/public void sendToALl(byte[] bytes){for (String ipAddress : communications.keySet()) {send(ipAddress,bytes);}}/*** @description: 给某个ip发送* @author liangxuelong* @date 2023/6/19 16:53* @version 1.0*/public boolean send(String ip,byte[] bytes) {if (communications.get(ip) == null)return false;try {communications.get(ip).send(bytes);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** @description: 当前是否启动 socket 服务端* @author liangxuelong* @date 2023/6/19 16:14* @version 1.0*/@Overridepublic boolean isStart() {return isConn;}/*** @description: 设置最大连接数量* @author * @date 2023/6/19 16:19* @version 1.0*/public void setMaxConnectSize(int maxConnectSize) {this.maxConnectSize = maxConnectSize;}/*** @description: 获取当前连接数据* @param:* @return: void* @author liangxuelong* @date: 2023/6/19*/public int getConnectSize(){return communications.size();}/*** @description: 获取当前所有连接的Ip地址* @param:* @return: void* @author liangxuelong* @date: 2023/6/19*/public Set<String> getConnectIpAddress(){return communications.keySet();}/*** @description: 添加连接对象* @author liangxuelong* @date 2023/6/19 15:14* @version 1.0*/protected void addCommunication(ICommunication communication) throws Exception {Socket socket = communication.getSocket();//判断是否超出最大连接数量,超出后断开连接if (maxConnectSize > communications.size()) {ICommunication iCommunication = communications.get(socket.getInetAddress().getHostAddress());if (iCommunication != null) {try {iCommunication.disconnect();} catch (Exception e) {e.printStackTrace();}communications.remove(socket.getInetAddress().getHostAddress());}communications.put(socket.getInetAddress().getHostAddress(),communication);} else {socket.close();throw new ConnectException(maxConnectSize);}}/*** @description: 移除连接对象* @author liangxuelong* @date 2023/6/19 15:14* @version 1.0*/public void removeCommunication(String ip){ICommunication iCommunication = communications.get(ip);if (iCommunication != null) {try {iCommunication.disconnect();} catch (Exception e) {e.printStackTrace();}communications.remove(ip);}}/*** @description: 移除所有连接对象* @author * @date 2023/6/19 15:14* @version 1.0*/public void removeAllCommunication(){for (String ipAddress : communications.keySet()) {removeCommunication(ipAddress);}}}


服务器端实现抽象类创建SocketServer类

/*** @author * @version 1.0* @description: socket 服务启动类* @date 2023/6/19 15:53*/
public class SocketServer extends AbstractSocketServer {public SocketServer(String ipAddress, int port) {super(ipAddress, port);}public SocketServer(int port) {super(port);}
}


客户端通讯接口ICommunication主要用于读写socket交互数据

public interface ICommunication {/*** @description: 获取当前连接的socket对象* @author * @date 2023/6/19 14:28* @version 1.0*/public Socket getSocket();/*** @description: socket创建成功后读取数据* @author * @date 2023/6/19 14:29* @version 1.0*/public void handle() throws Exception;/*** @description: 将读取到的数据统一处理* @author * @date 2023/6/19 14:29* @version 1.0*/public void receive(Socket socket,byte[] data) throws Exception;/*** @description: 发送数据* @author * @date 2023/6/19 14:41* @version 1.0*/public void send(byte[] data) throws Exception;/*** @description: 断开连接* @author liangxuelong* @date 2023/6/19 14:42* @version 1.0*/public void disconnect() throws Exception;
}



客户端实现通讯接口ICommunication创建SocketCommunication对象用于读写处理接收发送和发送数据

/*** @author * @version 1.0* @description: socket 连接对象* 主要用于对已连接的客户端收发消息* @date 2023/6/19 14:43*/
public class SocketCommunication implements ICommunication{private Socket socket; //已经连接的客户端对象private AbstractSocketServer socketServer; //来自哪个服务器,创建的服务器对象public SocketCommunication(@NotNull Socket socket, AbstractSocketServer socketServer) {this.socket = socket;this.socketServer = socketServer;}@Overridepublic Socket getSocket() {return socket;}@Overridepublic void handle() throws Exception {try {System.out.println(socket.getInetAddress().getHostAddress()+" 已连接");InputStream in = socket.getInputStream();ByteArrayOutputStream output = new ByteArrayOutputStream();byte[] b = new byte[1024];int len;while ( (len = in.read(b)) != -1) {output.write(b, 0, len);try {Thread.sleep(10);} catch (InterruptedException e1) {e1.printStackTrace();}if(in.available() == 0) {this.receive(socket,output.toByteArray());output.reset();}b = new byte[1024];len = 0;}} catch (IOException ioException) {throw ioException;}}/*** @description: 接收数据,对客户端接收的数据进行统一处理* 可以编写相应的处理逻辑,我这里是服务器端收到消息后。回复当前连接数量、* @author * @date 2023/6/19 17:30* @version 1.0*/@Overridepublic void receive(Socket socket, byte[] data) throws Exception {//服务器接收客户端消息System.out.println(socket.getInetAddress().getHostAddress()+" 发送:"+new String(data,"gbk"));//服务器回复客户端消息String msg = "当前连接数量:"+socketServer.getConnectSize();socketServer.send(socket.getInetAddress().getHostAddress(),msg.getBytes("gbk"));}/*** @description: 发送数据* @author * @date 2023/6/19 17:30* @version 1.0*/@Overridepublic void send(byte[] data) throws Exception {socket.getOutputStream().write(data);}/*** @description: 断开连接* @author * @date 2023/6/19 17:30* @version 1.0*/@Overridepublic void disconnect() throws Exception {System.out.println(socket.getInetAddress().getHostAddress()+" 已断开");socket.close();}}



定义一个自定义异常ConnectException处理连接数超出最大限制

/*** @author * @version 1.0* @description:* @date 2023/6/19 16:25*/
public class ConnectException extends Exception{public ConnectException(int maxSize) {super("连接数量超出最大限制,连接失败! 当前最大连接数:"+maxSize);}
}


最后定义main方法进行测试

/*** @author * @version 1.0* @description: TODO* @date 2024/2/9 15:57*/
public class Main {public static void main(String[] args) {SocketServer server = new SocketServer("192.168.0.100",5032);server.setMaxConnectSize(2); //设置最大连接数量server.startServer();//每5秒钟获取一下当前连接,并发送数据new Thread(() -> {while (true) {//获取所有连接for (String ip : server.getConnectIpAddress()) {try {System.out.println("当前已连接ip:"+ip);String msg = "向指定客户端发送消息: "+ip+" 你好";//向指定ip发送消息if (server.send(ip,msg.getBytes("gbk"))) {System.out.println("向 "+ip+" 发送了 ["+msg+"]");}} catch (UnsupportedEncodingException e) {e.printStackTrace();}}try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}}}).start();}
}

相关文章:

Java Socket Server TCP服务端向指定客户端发送消息

实现思路 首先需要知道java里如何创建一个Socket服务器端。 //创建一个服务器端对象ServerSocket server new ServerSocket(); //绑定启动的ip和端口号server.bind(new InetSocketAddress("127.0.0.1",8082));//启动成功后&#xff0c;调用accept()方法阻塞&#xf…...

java日志框架总结(五、logback日志框架)

一、logback概述 Logback是由log4j创始人设计的又一个开源日志组件。 Logback当前分成三个模块&#xff1a; 1、logback-core, 2、logback- classic 3、logback-access。 1&#xff09;logback-core是其它两个模块的基础模块。 2&#xff09;logback-…...

android下library打包aar并上传到maven,嵌入版的app

android嵌入版 准备工作简化代码到三方app上传maven自动打包上面已经完成了library到三方app的流程 这几天在研究android下怎么把自己的项目当作一个library给到另一个app做嵌入使用&#xff0c;把这些记录下来&#xff0c;方便以后参考 准备工作 1.需要了解一些gradle 命令打…...

Xampp中Xdebug的安装使用

工欲善其事&#xff0c;必先利其器 XDebug简介 XDebug 是一个用于 PHP 的调试和性能分析工具。它提供了一系列功能&#xff0c;帮助开发者在开发和调试 PHP 应用程序时更加高效。 以下是 XDebug 的一些主要特性和功能&#xff1a; 调试功能&#xff1a; 断点调试&#xff1a;…...

金融行业的软件测试分析

随着金融行业的业务不断增加&#xff0c;金融交易模式的不断变化&#xff0c;金融机构对信息化的要求也越来越高&#xff0c;高质量的金融软件对于金融机构来说显得尤为重要。如何保证金融行业软件的质量&#xff0c;对金融行业软件的测试人员来说&#xff0c;也提出了更高的要…...

踩坑了,MySQL数据库生成大量奇怪的大文件

作者&#xff1a;田逸&#xff08;formyz&#xff09; 一大早就收到某个数据库服务器磁盘满的报警信息&#xff0c;其中数据盘使用率超过90%&#xff0c;如下图所示。 这是一台刚上线不久的MySQL从库服务器&#xff0c;数据盘的总容量是300G。先登录系统&#xff0c;查看主从同…...

ctfshow-web11~20-WP

web11 根据提示,查询对ctfshow域名进行dns查询,查看TXT记录 阿里云查询链接:阿里云网站运维检测平台 获取flag成功 web12 根据题目提示,我们访问robots.txt,获取到后台地址 然后我们访问一下后台...

2.5学习总结9

并查集 知识点 并查集是一种数据结构&#xff0c;用于处理一些不相交集合的合并及查询问题。它支持两种操作&#xff1a; Find(x)&#xff1a;查找元素 x 所属的集合。Union(x, y)&#xff1a;将元素 x 所属的集合和元素 y 所属的集合合并。 初始化&#xff1a;将每个元素单…...

删除.git的影响、git分支切换时注意事项

一、删除.git的影响 master分支文件 dev分支文件 删除.git后 文件为删除.git前分支的文件状态。 二、git分支切换时注意事项 情景&#xff1a;如果我在分支A&#xff0c;想要跳转到分支B。 git的规矩是&#xff0c;在那个分支上进行的提交&#xff0c;就算哪个分支上的工作…...

Linux系统调试课:硬件断点

沉淀、分享、成长,让自己和他人都能有所收获!😄 📢在linux内核编程中,经常会遇到由于内存被篡改,例如 buffer overflow,野指针,write after free等。查找分析此类问题非常的麻烦。 一、什么是硬件断点 硬件断点,是Linux内核中是一种被ptrace和内核内调试器使用调试…...

百卓Smart管理平台 uploadfile.php 文件上传漏洞复现(CVE-2024-0939)

0x01 产品简介 百卓Smart管理平台是北京百卓网络技术有限公司(以下简称百卓网络)的一款安全网关产品,是一家致力于构建下一代安全互联网的高科技企业。 0x02 漏洞概述 百卓Smart管理平台 uploadfile.php 接口存在任意文件上传漏洞。未经身份验证的攻击者可以利用此漏洞上传…...

关于RabbitMQ常见的十道面试题

RabbitMQ是如何组成的&#xff1f;它有哪些重要的组件&#xff1f; RabbitMQ主要由以下几个重要组件组成&#xff1a; Broker&#xff1a;这是消息代理&#xff0c;主要负责接收、存储和转发消息Exchanges&#xff1a;交换器&#xff0c;它的主要作用是根据一定的规则匹配消息…...

spring cloud stream

背景 主要解决不同消息中间件切换问题。实现不同中间件的代码解耦。 链接: 支持的中间件 后文使用kafka测试。 引入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-stream</artifactId></depende…...

vue3 之 组合式API—watch函数

watch函数 作用&#xff1a;侦听一个或者多个数据的变化&#xff0c;数据变化时执行回调函数 两个额外参数&#xff1a; 1.immediate&#xff08;立即执行&#xff09;2.deep&#xff08;深度侦听&#xff09; 场景&#xff1a;比如选择不同的内容请求后端不同数据时 如下图 …...

并发容器【ConcurentHashMap、CopyOnWriteArrayList、阻塞队列、ArrayBlockingQueue】

并发容器 什么是并发容器?同步容器:并发容器: ConcurrentHashMap结构图JDK1.7结构图JDK1.8结构图 CopyOnWriteArrayList实现原理 并发队列阻塞队列ArrayBlockingQueue 转自极客时间 什么是并发容器? 在JUC包中&#xff0c;有一大部分是关于并发容器的&#xff0c;如Concurr…...

EmoLLM-心理健康大模型

宣传一下自己最近参与的开源 https://github.com/aJupyter/EmoLLM EmoLLM-心理健康大模型 EmoLLM 探索本项目的文档 查看Demo 报告Bug 提出新特性 EmoLLM 是一个能够支持 理解用户-支持用户-帮助用户 心理健康辅导链路的心理健康大模型&#xff0c;由 InternLM2 指令微…...

学成在线:采用XXL-JOB任务调度方案使用FFmpeg处理视频转码业务

分片技术方案 概述 XXL-JOB并不直接提供数据处理的功能&#xff0c;它只会给所有注册的执行器分配好分片序号&#xff0c;在向执行器下发任务调度的同时携带分片总数和当前分片序号等参数 设计作业分片方案保证多个执行器之间不会查询到重复的任务,保证任务不会重复执行 任…...

计算机毕业设计 | SpringBoot大型旅游网站 旅行后台管理系统(附源码)

1&#xff0c; 概述 1.1 项目背景 随着互联网技术的快速发展和普及&#xff0c;旅游行业逐渐转向线上&#xff0c;越来越多的游客选择在线预订旅游产品。传统的线下旅行社模式已不能满足市场需求&#xff0c;因此&#xff0c;开发一个高效、便捷的旅游网站成为行业的迫切需求…...

蓝桥杯----凑算式

这个算式中A~I代表1~9的数字,不同的字母代表不同的数字。 比如: 68/3952/714 就是一种解法, 53/1972/486 是另一种解法. 这个算式一共有多少种解法? 注意:你提交应该是个整数,不要填写任何多余的内容或说明性文字。 代码 public class _03凑算式 {static int a[] {1,2,3…...

JCTC | 利用几何深度学习对蛋白质-配体结合pose进行等变灵活建模

Overview 该论文解决了药物开发中蛋白质-配体复合结构灵活建模的挑战。作者提出了一种名为FlexPose的新型深度学习框架&#xff0c;它可以直接对复杂结构进行建模&#xff0c;而不需要传统的采样和评分策略。 该模型结合了标量-向量双特征表示和 SE(3)等变网络设计来处理动态结…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...