实现原理:

长连接的维持,是要客户端程序,定时向服务端程序,发送一个维持连接包的。
       如果,长时间未发送维持连接包,服务端程序将断开连接。

客户端:
       Client通过持有Socket的对象,可以随时(使用sendObject方法)发送Massage Object(消息)给服务端。
       如果keepAliveDelay毫秒(程序中是2秒)内未发送任何数据,则自动发送一个KeepAlive Object(心跳)给服务端,用于维持连接。
       由于,我们向服务端,可以发送很多不同的消息对象,服务端也可以返回不同的对象。所以,对于返回对象的处理,要编写具体的ObjectAction实现类进行处理。通过Client.addActionMap方法进行添加。这样,程序会回调处理。

服务端:
        由于客户端会定时(keepAliveDelay毫秒)发送维持连接的信息过来,所以,服务端要有一个检测机制。
        即当服务端receiveTimeDelay毫秒(程序中是3秒)内未接收任何数据,则自动断开与客户端的连接。
         ActionMapping的原理与客户端相似(相同)。

通过添加相应的ObjectAction实现类,可以实现不同对象的响应、应答过程。

心跳反映的代码:

*** * 维持连接的消息对象(心跳对象)*/
public class KeepAlive implements Serializable{private static final long serialVersionUID = -2813120366138988480L;/* 覆盖该方法,仅用于测试使用。* @see java.lang.Object#toString()*/@Overridepublic String toString() {return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"\t维持连接包";}}

客户端的代码:

public class Client {/*** 处理服务端发回的对象,可实现该接口。*/public static interface ObjectAction{void doAction(Object obj,Client client);}public static final class DefaultObjectAction implements ObjectAction{public void doAction(Object obj,Client client) {System.out.println("处理:\t"+obj.toString());}}public static void main(String[] args) throws UnknownHostException, IOException {String serverIp = "127.0.0.1";int port = 65432;Client client = new Client(serverIp,port);client.start();}private String serverIp;private int port;private Socket socket;private boolean running=false; //连接状态private long lastSendTime; //最后一次发送数据的时间//用于保存接收消息对象类型及该类型消息处理的对象private ConcurrentHashMap<Class, ObjectAction> actionMapping = new ConcurrentHashMap<Class,ObjectAction>();public Client(String serverIp, int port) {this.serverIp=serverIp;this.port=port;}public void start() throws UnknownHostException, IOException {if(running)return;socket = new Socket(serverIp,port);System.out.println("本地端口:"+socket.getLocalPort());lastSendTime=System.currentTimeMillis();running=true;new Thread(new KeepAliveWatchDog()).start();  //保持长连接的线程,每隔2秒项服务器发一个一个保持连接的心跳消息new Thread(new ReceiveWatchDog()).start();    //接受消息的线程,处理消息
    }public void stop(){if(running)running=false;}/*** 添加接收对象的处理对象。* @param cls 待处理的对象,其所属的类。* @param action 处理过程对象。*/public void addActionMap(Class<Object> cls,ObjectAction action){actionMapping.put(cls, action);}public void sendObject(Object obj) throws IOException {ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());oos.writeObject(obj);System.out.println("发送:\t"+obj);oos.flush();}class KeepAliveWatchDog implements Runnable{long checkDelay = 10;long keepAliveDelay = 2000;public void run() {while(running){if(System.currentTimeMillis()-lastSendTime>keepAliveDelay){try {Client.this.sendObject(new KeepAlive());} catch (IOException e) {e.printStackTrace();Client.this.stop();}lastSendTime = System.currentTimeMillis();}else{try {Thread.sleep(checkDelay);} catch (InterruptedException e) {e.printStackTrace();Client.this.stop();}}}}}class ReceiveWatchDog implements Runnable{public void run() {while(running){try {InputStream in = socket.getInputStream();if(in.available()>0){ObjectInputStream ois = new ObjectInputStream(in);Object obj = ois.readObject();System.out.println("接收:\t"+obj);ObjectAction oa = actionMapping.get(obj.getClass());oa = oa==null?new DefaultObjectAction():oa;oa.doAction(obj, Client.this);}else{Thread.sleep(10);}} catch (Exception e) {e.printStackTrace();Client.this.stop();} }}}}

服务短的代码:

public class Server {/*** 要处理客户端发来的对象,并返回一个对象,可实现该接口。*/public interface ObjectAction{Object doAction(Object rev, Server server);}public static final class DefaultObjectAction implements ObjectAction{public Object doAction(Object rev,Server server) {System.out.println("处理并返回:"+rev);return rev;}}public static void main(String[] args) {int port = 65432;Server server = new Server(port);server.start();}private int port;private volatile boolean running=false;private long receiveTimeDelay=3000;private ConcurrentHashMap<Class, ObjectAction> actionMapping = new ConcurrentHashMap<Class,ObjectAction>();private Thread connWatchDog;public Server(int port) {this.port = port;}public void start(){if(running)return;running=true;connWatchDog = new Thread(new ConnWatchDog());connWatchDog.start();}@SuppressWarnings("deprecation")public void stop(){if(running)running=false;if(connWatchDog!=null)connWatchDog.stop();}public void addActionMap(Class<Object> cls,ObjectAction action){actionMapping.put(cls, action);}class ConnWatchDog implements Runnable{public void run(){try {ServerSocket ss = new ServerSocket(port,5);while(running){Socket s = ss.accept();new Thread(new SocketAction(s)).start();}} catch (IOException e) {e.printStackTrace();Server.this.stop();}}}class SocketAction implements Runnable{Socket s;boolean run=true;long lastReceiveTime = System.currentTimeMillis();public SocketAction(Socket s) {this.s = s;}public void run() {while(running && run){if(System.currentTimeMillis()-lastReceiveTime>receiveTimeDelay){overThis();}else{try {InputStream in = s.getInputStream();if(in.available()>0){ObjectInputStream ois = new ObjectInputStream(in);Object obj = ois.readObject();lastReceiveTime = System.currentTimeMillis();System.out.println("接收:\t"+obj);ObjectAction oa = actionMapping.get(obj.getClass());oa = oa==null?new DefaultObjectAction():oa;Object out = oa.doAction(obj,Server.this);if(out!=null){ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());oos.writeObject(out);oos.flush();}}else{Thread.sleep(10);}} catch (Exception e) {e.printStackTrace();overThis();} }}}private void overThis() {if(run)run=false;if(s!=null){try {s.close();} catch (IOException e) {e.printStackTrace();}}System.out.println("关闭:"+s.getRemoteSocketAddress());}}}

转载于:https://www.cnblogs.com/zqyanywn/p/7171969.html

JAVA实现长连接(含心跳检测)Demo相关推荐

  1. Socket Client 长连接及心跳检测

    简介: 所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象.一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制.从所处的地位来讲,套接 ...

  2. java nio socket长连接_nio实现Socket长连接和心跳

    前段时间用bio方式,也就是传统io实现了socket的长连接和心跳,总觉着服务端开启多线程管理socket连接的方式过于消耗资源,数据并发的情况下可能会影响到性能,因此就尝试使用nio改进原来的代码 ...

  3. 聊聊 TCP 长连接和心跳那些事

    1 前言 可能很多 Java 程序员对 TCP 的理解只有一个三次握手,四次挥手的认识,我觉得这样的原因主要在于 TCP 协议本身稍微有点抽象(相比较于应用层的 HTTP 协议):其次,非框架开发者不 ...

  4. java前端长连接框架_Java如何实现长连接

    实现原理: 长连接的维持,是要客户端程序,定时向服务端程序,发送一个维持连接包的. 如果,长时间未发送维持连接包,服务端程序将断开连接. 客户端: Client通过持有Socket的对象,可以随时(使 ...

  5. TCP长连接,心跳机制介绍

    TCP长连接,心跳机制介绍 长连接 为何要长连接 心跳 心跳为何设置在服务器端 心跳维持长连接 TCP keep-alive的三个参数 参数的具体意义 心跳的使用场景 长连接 TCP经过三次握手建立连 ...

  6. 长连接、心跳和断线重连

    长连接.心跳和断线重连 2017年06月22日 18:38:53 天涯遍地是小草 阅读数 7938 一.概述 目前IM软件有一个基本的功能就是长在线,即只要有网络就保持登录,然而,网络状态是无法预测的 ...

  7. linux测试tcp长连接工具,Linux(服务器编程):44---TCP长连接、短连接(心跳检测)

    一.TCP连接的相关说明 ①使用TCP协议时,会在客户端和服务器之间建立一条虚拟的信道,这条虚拟信道就是指连接,而建议这条连接需要3次握手,拆毁这条连接需要4次挥手,可见,我们建立这条连接是有成本的, ...

  8. JAVA调用mq时做心跳检测,[翻译]RabbitMQ 心跳

    用心跳检测死TCP连接 介绍 网络可能会以许多方式失败,有时会很细微(例如高比率的数据包丢失).中断的TCP连接需要比较长时间(例如,在Linux上默认是大约11分钟)才能被操作系统检测到.AMQP ...

  9. java nio长连接实现_kio: kio是基于jdk 1.6 nio实现的TCP长连接即时通讯框架。

    #kio: TCP长连接框架 适用于Android前端 #为何要开发kio# 由于之前开发的Android推送系统,使用HTTP实现的,随着业务的扩展,服务器的压力随之增大,开始考虑使用TCP长连接来 ...

最新文章

  1. Eclipse中10个最有用的快捷键组合
  2. AddressSanitizer+cmake
  3. 【Android 插件化】基于插件化的恶意软件的加载策略分析 ( 自定义路径加载插件 | 系统路径加载插件 | 用户同意后加载插件 | 隐藏恶意插件 )
  4. 【Linux】一步一步学Linux——w命令(227)
  5. PHP防SQL注入攻击
  6. gitignore忽略文件夹_原创 | 详解gitignore的使用方法,让你尽情使用git add .
  7. python webdriver save_Python + Selenium +Chrome 批量下载网页代码修改【新手必学】
  8. bcp大容量复制实用工具_运行中的BCP(大容量复制程序)命令
  9. mini_c编译器的简单代码逻辑
  10. buff系统 游戏中_泛娱产业:ARPG游戏的技能系统和buff系统的一种实现
  11. flv.js简单使用示例
  12. [油猴脚本] 知乎免广告
  13. English trip V1 - 23. Big and Bigger Teacher:Corrine Key: adjective comparisons 形容词 比较级
  14. Wordpress建站教程:网站SEO优化
  15. 百度年龄计算机在线使用,百度精准年龄计算器在线计算app
  16. 企业级运维——Mysql主从复制(异步、半同步、全同步)
  17. c语言西南交通大学出版社答案,西南交通大学C++上机实验答案
  18. pytohn用Pillow或OpenCV删除图片某种颜色
  19. 在markdown下用mma画函数图像
  20. npm全局安装和本地安装及卸载

热门文章

  1. Linux10-归档、系统间复制文件
  2. go语言学习-iota
  3. 比特币挖矿——区块链技术
  4. mac gource_如何使用Gource显示项目的时间表
  5. 女性程序员大会ghc_在女性科技大会上成为男人的感觉
  6. Linux qgis 编译,QGIS简介与源代码编译
  7. win8系统的计算机共享在哪里设置方法,怎么设置win8无线共享呢?
  8. html中radio、checkbox选中状态研究(静下心来看,静下心来总结)
  9. Javascript及Jquery获取元素节点以及添加和删除操作
  10. 【转载】mysql常用函数汇总