Java implementa monitoreo de latidos

Antes que nada, déjame decirte que debe haber más de una forma de realizar el monitoreo de latidos, antes de hacerlo, el requisito dado por el líder fue usar netty para implementarlo, después de verlo por más de un día, un pequeño La demostración se completó con netty, pero se descubrió cuando se conectó el servidor.socket io. Así que cambié a la implementación de socket io.
Debe haber otras implementaciones, pero como no lo he cubierto, no hablaré de eso por el momento, comencemos con netty.

neto

El primer paso: paquete de guía

        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>5.0.0.Alpha2</version
        </dependency>

Con respecto a este paquete de netty, muchas personas en Internet han dicho que netty es compatible con versiones anteriores. Pero debido a que en realidad no lo he encontrado, no puedo dar un buen consejo. Solo puedo decir que si encuentra problemas, puede pensar en ello en esta dirección.
Código. De hecho, esto involucra cosas muy esotéricas, ¡como codificar y decodificar! Pero debido a que lo que tengo que hacer es relativamente simple, no he mirado este aspecto con mucho cuidado. ¡Mientras implemente un monitoreo simple de latidos cardíacos aquí, estará bien!
Implemente principalmente la clase SimpleChannelInboundHandler<String>. Cabe señalar que las diferentes versiones de netty tienen nombres de métodos ligeramente diferentes, como messageReceive, y algunas versiones se denominan clientRead0. Esto es solo al azar.

package com.dsyl.done.netty;
 
import java.io.IOException;
import java.util.Date;
import java.util.concurrent.TimeUnit;
 
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.EventLoop;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.ReferenceCountUtil;
 
public class HeartBeatClientHandler extends SimpleChannelInboundHandler<String> {
 
      private ClientStarter clientStarter;
 
      public HeartBeatClientHandler(ClientStarter clientStarter) {
        this.clientStarter = clientStarter;
      }
 
      /**
       * 客户端监听写事件。也就是设置时间内没有与服务端交互则发送ping 给服务端
       */
      @Override
      public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if(evt instanceof IdleStateEvent) {
          IdleState state = ((IdleStateEvent)evt).state();
          if(state == IdleState.ALL_IDLE) {
            ctx.writeAndFlush("PING");
            System.out.println("send PING");
          }
        }
        super.userEventTriggered(ctx, evt);
      }
      /**
       * channelInactive 被触发一定是和服务器断开了。分两种情况。一种是服务端close,一种是客户端close。
       */
      @Override
      public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        System.err.println("客户端与服务端断开连接,断开的时间为:"+(new Date()).toString());
        // 定时线程 断线重连
        final EventLoop eventLoop = ctx.channel().eventLoop();
        //设置断开连接后重连时间,此设置是断开连接一分钟(60秒)后重连
        eventLoop.schedule(() -> clientStarter.connect(), 60, TimeUnit.SECONDS);
      }
 
      /**
       * 在服务器端不使用心跳检测的情况下,如果客户端突然拔掉网线断网(注意这里不是客户度程序关闭,而仅是异常断网)
       */
      @Override
      public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        if(cause instanceof IOException) {
          System.out.println("server "+ctx.channel().remoteAddress()+"关闭连接");
        }
      }
 
    /**
     * 消息监控,监听服务端传来的消息(和netty版本有关,有的版本这个方法叫做clientRead0)
     */
      @Override
    protected void messageReceived(ChannelHandlerContext ctx, String msg) throws Exception {
        if (msg.equals("PONG")) {
              System.out.println("receive form server PONG");
            }
            ReferenceCountUtil.release(msg);
         
    }
    }

package com.dsyl.done.netty;
 
import java.net.InetSocketAddress;
 
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;
 
public class ClientStarter {
 
    private Bootstrap bootstrap;
    private int times = 0;
 
    public ClientStarter(Bootstrap bootstrap) {
        this.bootstrap = bootstrap;
        ClientStarter clientStarter = this;
        bootstrap.group(new NioEventLoopGroup())
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new StringEncoder());
                        ch.pipeline().addLast(new StringDecoder());
                        //发送消息频率。单位秒。此设置是60秒发送一次消息
                        ch.pipeline().addLast(new IdleStateHandler(60, 60, 60));
                        ch.pipeline().addLast(new HeartBeatClientHandler(clientStarter));
                    }
                });
    }
 
    public void connect() {
        ChannelFuture channelFuture = bootstrap.connect(new InetSocketAddress("ip", 端口));
        channelFuture.addListener(future ->{
                if (future.isSuccess()) {
                    System.out.println("connect to server success");
                } else {
                    System.out.println("connect to server failed,try times:" + ++times);
                    connect();
                }
        });
    }
}

Esto completa la configuración. Al realizar la prueba, simplemente cree un nuevo objeto ClientStarter y llame al método de inicio.

ClientStarter starter = new ClientStarter(new Bootstrap());
starter.connect();

Luego, cuando realice la prueba, cree un servidor localmente y pruebe bien, pero hay un problema con la depuración conjunta con el servidor:

Esto se debe a que el servidor desconecta al cliente después de que la conexión es exitosa. Luego repita el proceso. Este es un problema de configuración del lado del servidor.

enchufe io

Esto se puede considerar como una especie de encapsulación en netty. De todos modos, es más simple y más conveniente de usar que netty. Lo usa principalmente nuestro servidor, así que lo cambié a esta forma.
El primer paso es guiar el paquete.

<!-- netty socketio -->
        <dependency>
            <groupId>com.corundumstudio.socketio</groupId>
            <artifactId>netty-socketio</artifactId>
            <version>1.7.13</version>
        </dependency>

        <dependency>
            <groupId>io.socket</groupId>
            <artifactId>socket.io-client</artifactId>
            <version>1.0.0</version>
        </dependency>

Permítanme hablar sobre esto aquí, lo siguiente es la dependencia que el cliente necesita importar y lo anterior. . . ¿Se debe importar el servidor? De todos modos, miré el código del proyecto de nuestro servidor y se importaron ambas dependencias.
Déjame ir directamente a mi código local, es bastante simple:

    public void connectServer() {
        String url = "http://" + serverListenIp;
        try {
            IO.Options options = new IO.Options();
            options.transports = new String[] { "websocket" };
            options.reconnectionAttempts = 1000000000;
            options.reconnectionDelay = 60000;// 失败重连的时间间隔
            options.timeout = 10000;// 连接超时时间(ms)
            // par1 是任意参数
            final Socket socket = IO.socket(url + "?userType=0", options);
            socket.on(Socket.EVENT_CONNECT, objects -> {
                System.out.println("client: 连接成功");
                System.out.println("拉取缓存的数据信息!");
                //做你想做的操作
            });
            socket.on(Socket.EVENT_CONNECTING, objects -> System.out.println("client: " + "连接中"));
            socket.on(Socket.EVENT_CONNECT_TIMEOUT, objects -> System.out.println("client: " + "连接超时"));
            socket.on(Socket.EVENT_CONNECT_ERROR, objects -> System.out.println("client: " + "连接失败"));
            socket.connect();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

Aquí Socket.EVENT_CONNECT, Socket.EVENT_CONNECTING, etc. se dan constantes. Si no entiendes, puedes mirar la definición.


 

Supongo que te gusta

Origin blog.csdn.net/m0_69824302/article/details/130544738
Recomendado
Clasificación