Java BIO tcp服务端向客户端消息群发代码教程实战

简介: java BIO tcp服务端向客户端消息群发代码教程实战

前言

  项目需要和第三方厂商的服务需要用TCP协议通讯,考虑到彼此双方可能都会有断网重连、宕机重启的情况,需要保证 发生上述情况后,服务之间能够自动实现重新通信。研究测试之后整理如下代码实现。因为发现客户端重启后,对于服务端来说原来的客户端和服务端进程进程已经关闭,启动又和服务端新开了一个进程。所以实现原理就可以通过服务端向客户端群发实现,断开重新连接通讯。

代码

tcp服务端代码

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class HttpSocketServer {
    public static void main(String[] args) {
        try {
            ServerSocket server=new ServerSocket(9020);
            while (true){
                Socket client=server.accept();
                client.setKeepAlive(true);
                client.setOOBInline(true);
                System.out.println("进入了1个客户机连接:"+client.getRemoteSocketAddress().toString());
                ServerThread st = new ServerThread(client);
                st.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

image.gif

ServerThread 线程类

import java.io.*;
import java.net.Socket;
/**
 * 客户机   线程 ——自动执行run
 * @author Lenovo
 */
public class ServerThread extends Thread{
    private Socket client;
    /**
     * 方法描述: 用有参构造  接收主函数那边传来的 客户机
     */
    public ServerThread(Socket client) {
        this.client=client;
    }
    @Override
    public void run() {
        try {
            processSocket();//调用你想执行的 使线程启动时在run方法开始执行
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 调用以上方法
     */
    public void processSocket() throws IOException {
        //加入集合 便于服务器群发
        TcpTool.addSocket(client);
    }

image.gif

TcpTool 消息群发工具类

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
/**
 * 聊天工具类
 * @author tarzan
 */
public class TcpTool {
    private static List<Socket> clientList=new ArrayList<Socket>();
    /**
     * 便于 验证成功后  加入客户机
     * @param socket
     */
    public static void addSocket(Socket socket) {
        clientList.add(socket);
    }
    /**
     * 群发=遍历list中的all元素, 对每个元素 写出
     * @param msg
     * @throws IOException
     */
    public static void sendAll(String msg){
        for (int i = 0; i <clientList.size(); i++) {
            Socket client = clientList.get(i);
            if(clientIsClose(client)){
                delSocket(client);
                i--;
                continue;
            }
            try {
                OutputStream ops =  client.getOutputStream();
                ops.write((msg+"\r\n").getBytes());
                ops.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 判断是否断开连接,断开返回true,没有返回false
     * @param socket
     * @return
     */
    public static Boolean clientIsClose(Socket socket){
        try{
            //发送1个字节的紧急数据,默认情况下,服务器端没有开启紧急数据处理,不影响正常通信
            socket.sendUrgentData(0xFF);
            // 发送一个数据包, 如果通信正常就不会报错.  没有报错说明没有关闭., 返回false
            return false;
        }catch(Exception se){
            return true;
        }
    }
    /**
     * 下线时删除
     * @param socket
     */
    public static void delSocket(Socket socket){
        clientList.remove(socket);
    }
}

image.gif

Tcp客户端代码

import org.springblade.core.tool.utils.StringUtil;
import java.io.*;
import java.net.Socket;
/**
 * @author tarzan
 */
public class HttpSocketClient {
    public static void main(String[] args) throws IOException {
        Socket client=new Socket("127.0.0.1",9020);
        client.setKeepAlive(true);
        client.setOOBInline(true);
        while (true) {
            try {
                if (!clientIsClose(client)) {
                    InputStream is=client.getInputStream();
                    BufferedReader reader=new BufferedReader(new InputStreamReader(is));
                    String text=reader.readLine();
                    if(StringUtil.isNotBlank(text)){
                        System.out.println("来自服务端的消息:"+text);
                    }
                }else{
                    try {
                        //断开5秒后重新连接
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    client=new Socket("127.0.0.1",9020);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static Boolean clientIsClose(Socket socket){
        try{
            //发送1个字节的紧急数据,默认情况下,服务器端没有开启紧急数据处理,不影响正常通信
            socket.sendUrgentData(0xFF);
            // 发送一个数据包, 如果通信正常就不会报错.  没有报错说明没有关闭., 返回false
            return false;
        }catch(Exception se){
            return true;
        }
    }

image.gif

运行一个服务端,启动多个客户端进行测试。

控制台输出

image.gif编辑

以上只是实现的最简单的demo,服务端,因为服务端和客户端都需要不断监听彼此通信,发送消息时候,需要另起一个线程,调用TcpTool工具类想客户端群发消息。

相关文章
|
14天前
|
分布式计算 Java Hadoop
Hadoop-30 ZooKeeper集群 JavaAPI 客户端 POM Java操作ZK 监听节点 监听数据变化 创建节点 删除节点
Hadoop-30 ZooKeeper集群 JavaAPI 客户端 POM Java操作ZK 监听节点 监听数据变化 创建节点 删除节点
34 1
|
19天前
|
JSON Java 开发工具
Java服务端集成Google FCM推送的注意事项和实际经验
公司的app要上海外,涉及到推送功能,经过综合考虑,选择Google FCM进行消息推送。 查看一些集成博客和官方文档,看的似懂非懂,迷迷惑惑。本篇文章除了将我实际集成的经验分享出来,也会对看到的博客及其中产生的疑惑、注意事项一一评论。 从官方文档和众多博客中,你会发现Java集成FCM推送有多种实现方式,会让生产生文档很乱,不知作何选择的困惑。
46 0
|
1月前
|
JSON NoSQL Java
redis的java客户端的使用(Jedis、SpringDataRedis、SpringBoot整合redis、redisTemplate序列化及stringRedisTemplate序列化)
这篇文章介绍了在Java中使用Redis客户端的几种方法,包括Jedis、SpringDataRedis和SpringBoot整合Redis的操作。文章详细解释了Jedis的基本使用步骤,Jedis连接池的创建和使用,以及在SpringBoot项目中如何配置和使用RedisTemplate和StringRedisTemplate。此外,还探讨了RedisTemplate序列化的两种实践方案,包括默认的JDK序列化和自定义的JSON序列化,以及StringRedisTemplate的使用,它要求键和值都必须是String类型。
redis的java客户端的使用(Jedis、SpringDataRedis、SpringBoot整合redis、redisTemplate序列化及stringRedisTemplate序列化)
|
2月前
|
Java
Java使用FileInputStream&&FileOutputStream模拟客户端向服务器端上传文件(单线程)
Java使用FileInputStream&&FileOutputStream模拟客户端向服务器端上传文件(单线程)
72 1
|
2月前
|
Java
"揭秘Java IO三大模式:BIO、NIO、AIO背后的秘密!为何AIO成为高并发时代的宠儿,你的选择对了吗?"
【8月更文挑战第19天】在Java的IO编程中,BIO、NIO与AIO代表了三种不同的IO处理机制。BIO采用同步阻塞模型,每个连接需单独线程处理,适用于连接少且稳定的场景。NIO引入了非阻塞性质,利用Channel、Buffer与Selector实现多路复用,提升了效率与吞吐量。AIO则是真正的异步IO,在JDK 7中引入,通过回调或Future机制在IO操作完成后通知应用,适合高并发场景。选择合适的模型对构建高效网络应用至关重要。
60 2
|
3月前
|
消息中间件 Java Kafka
Java 客户端访问kafka
Java 客户端访问kafka
39 9
|
3月前
|
安全 Java Linux
(七)Java网络编程-IO模型篇之从BIO、NIO、AIO到内核select、epoll剖析!
IO(Input/Output)方面的基本知识,相信大家都不陌生,毕竟这也是在学习编程基础时就已经接触过的内容,但最初的IO教学大多数是停留在最基本的BIO,而并未对于NIO、AIO、多路复用等的高级内容进行详细讲述,但这些却是大部分高性能技术的底层核心,因此本文则准备围绕着IO知识进行展开。
144 1
|
2月前
|
Java
Java模拟文件发送给服务器,服务器将文件转发给其他用户,并保存到服务器本地,其他用户可以接收,并保存到本地磁盘,支持各种文件格式,并解决通信中服务器怎么区分客户端发来的文件类型
Java模拟文件发送给服务器,服务器将文件转发给其他用户,并保存到服务器本地,其他用户可以接收,并保存到本地磁盘,支持各种文件格式,并解决通信中服务器怎么区分客户端发来的文件类型
|
3月前
|
网络协议 Java 数据处理
(一)Java网络编程之计网基础、TCP-IP协议簇、TCP、UDP协议及腾讯QQ通信原理综述
就目前而言,多数网络编程的系列的文章都在围绕着计算机网络体系进行阐述,但其中太多理论概念,对于大部分开发者而言,用途甚微。因此,在本系列中则会以实际开发者的工作为核心,从Java程序员的角度出发,详细解读Java的网络编程核心内容。
|
3月前
|
网络协议 Java
如何在Java中使用Socket编程实现TCP连接?
在Java中,通过Socket编程实现TCP连接非常常见。以下演示了基本的TCP通信流程,可根据具体需求进行扩展。
196 0