Java: server/client 心跳机制实现 示例

心跳机制

心跳机制是定时发送一个自定义的结构体(心跳包),让对方知道自己还活着,以确保连接的有效性的机制。

大部分CS的应用需要心跳机制。心跳机制一般在Server和Client都要实现,两者实现原理基本一样。Client不关心性能,怎么做都行。

如果应用是基于TCP的,可以简单地通过SO_KEEPALIVE实现心跳。TCP在设置的KeepAlive定时器到达时向对端发一个检测TCP segment,如果没收到ACK或RST,尝试几次后,就认为对端已经不存在,最后通知应用程序。这里有个缺点是,Server主动发出检测包,对性能有点影响。

应用自己实现 
Client启动一个定时器,不断发心跳; 
Server收到心跳后,给个回应; 
Server启动一个定时器,判断Client是否存在,判断方法这里列两种: 
时间差和简单标志。

  1. 时间差策略

    收到一个心跳后,记录当前时间(记为recvedTime)。

    判断定时器时间到达,计算多久没收到心跳的时间(T)=当前时间 - recvedTime(上面记录的时间)。如果T大于某个设定值,就可以认为Client超时了。

  2. 简单标志

    收到一个心跳后,设置连接标志为true;

    判断定时器时间到达,查看所有的标志,false的,认为对端超时了;true的将其设成false。

    上面这种方法比上面简单一些,但检测某个Client是否离线的误差有点大。

Demo

此处我们实现一个发送对象,例子简陋,实际在工作中还需按需求修改。

实体类

package com.lee.entity;

import java.io.Serializable;

public class Entity implements Serializable {

    private static final long serialVersionUID = 1L;
    private String name;
    private String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "Entity [name=" + name + ", sex=" + sex + "]";
    }

}

服务端

ServerHeart.java

package com.lee.server;

import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;

import com.lee.entity.Entity;

public class ServerHeart extends Thread {

    private ServerSocket server = null;
    Object obj = new Object();

    @Override
    public void run() {
        try {
            server = new ServerSocket(9090);

            while (true) {
                Socket client = server.accept();
                synchronized (obj) {
                    new Thread(new Client(client)).start();
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 客户端线程
     *
     * @author USER
     *
     */
    class Client implements Runnable {
        Socket client;

        public Client(Socket client) {
            this.client = client;
        }

        @Override
        public void run() {
            try {
                while (true) {
                    ObjectInput in = new ObjectInputStream(client.getInputStream());
                    Entity entity = (Entity) in.readObject();
                    System.out.println(entity);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 程序的入口main方法
     *
     * @param args
     */
    public static void main(String[] args) {
        System.out.println("开始检测客户端是否在线...");
        new ServerHeart().start();
    }
}

客户端

ClientHeart.java

package com.lee.client;

public class ClientHeart extends Thread {

    @Override
    public void run() {

        try {
            while (true) {
                ClientSender.getInstance().send();
                synchronized (ClientHeart.class) {
                    // this.wait(5000);
                    Thread.sleep(2000);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 程序的入口main方法
     *
     * @param args
     */
    public static void main(String[] args) {
        ClientHeart client = new ClientHeart();
        client.start();
    }

}

ClientSender.java

package com.lee.client;

import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;

import com.lee.entity.Entity;

public class ClientSender {

    private ClientSender() {
    }

    Socket sender = null;
    private static ClientSender instance;

    public static ClientSender getInstance() {
        if (instance == null) {
            synchronized (ClientHeart.class) {
                instance = new ClientSender();
            }
        }
        return instance;
    }

    public void send() {
        try {
            sender = new Socket(InetAddress.getLocalHost(), 9090);
            while (true) {
                ObjectOutputStream out = new ObjectOutputStream(sender.getOutputStream());
                Entity obj = new Entity();
                obj.setName("xiaoming");
                obj.setSex("男");
                out.writeObject(obj);
                out.flush();

                System.out.println("已发送...");
                Thread.sleep(5000);
            }
        } catch (Exception e) {

        }
    }
}

时间: 2024-10-27 06:19:32

Java: server/client 心跳机制实现 示例的相关文章

java -server 和 -client 的不同,及 java -server 时抛错原因

在dos窗口运行:java -server Error: missing `server' JVM at `C:\Program Files\Java\jre7\bin\server\jvm.dll'. Please install or use the JRE or JDK that contains these missing components. 网上的意思: 找到jdk安装目录下面 jre\bin 里面有 client 和 server 文件夹. 把 server 文件夹复制到 C:\

Java设置Client Socket链接Server超时时间

Java设置Client Socket链接Server超时时间 学习了:http://blog.csdn.net/tterminator/article/details/52494141 http://blog.csdn.net/fw0124/article/details/41227543 整理如下: Socket client = null; // 创建一个流套接字,连接到指定主机上的指定端口号 // client = new Socket(IP, PORT); client = new S

netty之心跳机制

1.心跳机制,在netty3和netty5上面都有.但是写法有些不一样. 2.心跳机制在服务端和客户端的作用也是不一样的.对于服务端来说:就是定时清除那些因为某种原因在一定时间段内没有做指定操作的客户端连接.对于服务端来说:用来检测是否断开连接,然后尝试重连等问题.游戏上面也可以来监控延时问题. 3.我这边只写了服务端的心跳用法,客户端基本差不多. 1)netty3的写法 import org.jboss.netty.bootstrap.ServerBootstrap; import org.j

Dubbo服务合买平台搭建出售发布之服务暴露&心跳机制&服务注册

Dubbo服务发布 Dubbo合买平台搭建出售 dsluntan.com Q:3393756370 VX:17061863513服务发布影响流程的主要包括三个部分,依次是: 服务暴露 心跳 服务注册 服务暴露是对外提供服务及暴露端口,以便消费端可以正常调通服务.心跳机制保证服务器端及客户端正常长连接的保持,服务注册是向注册中心注册服务暴露服务的过程. Dubbo服务暴露 此处只记录主要代码部分以便能快速定位到主要的核心代码: ServiceConfig.java中代码 if (registryU

Netty 实现心跳机制.md

netty 心跳机制示例,使用netty4,IdleStateHandler 实现. 本文假设你已经了解了Netty的使用,或者至少写过netty的helloworld,知道了netty的基本使用.我们知道使用netty的时候,大多数的东西都与Handler有关,我们的业务逻辑基本都是在Handler中实现的.Netty中自带了一个IdleStateHandler 可以用来实现心跳检测. 心跳检测的逻辑 本文中我们将要实现的心跳检测逻辑是这样的:服务端启动后,等待客户端连接,客户端连接之后,向服

基于netty实现的长连接,心跳机制及重连机制

技术:maven3.0.5 + netty4.1.33 + jdk1.8 概述 Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序. 也就是说,Netty 是一个基于NIO的客户.服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户.服务端应用.Netty相当于简化和流线化了网络应用的编程开发过程,例如:基于TCP和UDP的socket服务

Netty学习篇④-心跳机制及断线重连

心跳检测 前言 客户端和服务端的连接属于socket连接,也属于长连接,往往会存在客户端在连接了服务端之后就没有任何操作了,但还是占用了一个连接:当越来越多类似的客户端出现就会浪费很多连接,netty中可以通过心跳检测来找出一定程度(自定义规则判断哪些连接是无效链接)的无效链接并断开连接,保存真正活跃的连接. 什么叫心跳检测 我理解的心跳检测应该是客户端/服务端定时发送一个数据包给服务端/客户端,检测对方是否有响应: 如果是存活的连接,在一定的时间内应该会收到响应回来的数据包: 如果在一定时间内

Ambari窥探分布式心跳机制

Ambari是在Hadoop大数据生态圈的基础上应运而生,Ambari的架构也借助了分布式的思想,细细品味,与Hadoop分布式架构有很多相似之处. Hadoop中单NN 与多DN的通信是借助netty封装的RPC机制实现,单Ambari server与多Agent通信则是基于restful api + json实现,rpc与rest api的争论不是本文要讨论的重点,我们追求的目标只有一个,完美实现业务需求. 心跳设计一个主要的原因是判断客户端是否在线,每隔一段时间会发送数据交互.Ambari

MapReduce剖析笔记之四:TaskTracker通过心跳机制获取任务的流程

上一节分析到了JobTracker把任务从队列里取出来并进行了初始化,所谓的初始化,主要是获取了Map.Reduce任务的数量,并统计了哪些DataNode所在的服务器可以处理哪些Split等等,将这些信息缓存起来,但还没有进行实质的分配.等待TaskTracker跟自己通信. TaskTracker一般运行于DataNode之上,下面是他的声明,可见,是一个线程类: /******************************************************* * TaskT