• JAVA实现长连接(含心跳检测)Demo


    实现原理:

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

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

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

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

    心跳反映的代码:

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

    }

    复制代码

    客户端的代码:

    复制代码
    public class Client {
    
    </span><span style="color: #008000">/**</span><span style="color: #008000">
     * 处理服务端发回的对象,可实现该接口。
     </span><span style="color: #008000">*/</span>
    <span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">interface</span><span style="color: #000000"> ObjectAction{
        </span><span style="color: #0000ff">void</span><span style="color: #000000"> doAction(Object obj,Client client);
    }
    
    </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">final</span> <span style="color: #0000ff">class</span> DefaultObjectAction <span style="color: #0000ff">implements</span><span style="color: #000000"> ObjectAction{
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> doAction(Object obj,Client client) {
            System.out.println(</span>"处理:	"+<span style="color: #000000">obj.toString());
        }
    }
    
    
    </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> main(String[] args) <span style="color: #0000ff">throws</span><span style="color: #000000"> UnknownHostException, IOException {
        String serverIp </span>= "127.0.0.1"<span style="color: #000000">;
        </span><span style="color: #0000ff">int</span> port = 65432<span style="color: #000000">;
        Client client </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> Client(serverIp,port);
        client.start();
    }
    
    </span><span style="color: #0000ff">private</span><span style="color: #000000"> String serverIp;
    </span><span style="color: #0000ff">private</span> <span style="color: #0000ff">int</span><span style="color: #000000"> port;
    </span><span style="color: #0000ff">private</span><span style="color: #000000"> Socket socket;
    </span><span style="color: #0000ff">private</span> <span style="color: #0000ff">boolean</span> running=<span style="color: #0000ff">false</span>; <span style="color: #008000">//</span><span style="color: #008000">连接状态</span>
    
    <span style="color: #0000ff">private</span> <span style="color: #0000ff">long</span> lastSendTime; <span style="color: #008000">//</span><span style="color: #008000">最后一次发送数据的时间
    
    </span><span style="color: #008000">//</span><span style="color: #008000">用于保存接收消息对象类型及该类型消息处理的对象</span>
    <span style="color: #0000ff">private</span> ConcurrentHashMap&lt;Class, ObjectAction&gt; actionMapping = <span style="color: #0000ff">new</span> ConcurrentHashMap&lt;Class,ObjectAction&gt;<span style="color: #000000">();
    
    </span><span style="color: #0000ff">public</span> Client(String serverIp, <span style="color: #0000ff">int</span><span style="color: #000000"> port) {
        </span><span style="color: #0000ff">this</span>.serverIp=<span style="color: #000000">serverIp;
        </span><span style="color: #0000ff">this</span>.port=<span style="color: #000000">port;
    }
    
    </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> start() <span style="color: #0000ff">throws</span><span style="color: #000000"> UnknownHostException, IOException {
        </span><span style="color: #0000ff">if</span>(running)<span style="color: #0000ff">return</span><span style="color: #000000">;
        socket </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> Socket(serverIp,port);
        System.out.println(</span>"本地端口:"+<span style="color: #000000">socket.getLocalPort());
        lastSendTime</span>=<span style="color: #000000">System.currentTimeMillis();
        running</span>=<span style="color: #0000ff">true</span><span style="color: #000000">;
        </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span> KeepAliveWatchDog()).start();  <span style="color: #008000">//</span><span style="color: #008000">保持长连接的线程,每隔2秒项服务器发一个一个保持连接的心跳消息</span>
        <span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span> ReceiveWatchDog()).start();    <span style="color: #008000">//</span><span style="color: #008000">接受消息的线程,处理消息</span>
    

    }

    </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> stop(){
        </span><span style="color: #0000ff">if</span>(running)running=<span style="color: #0000ff">false</span><span style="color: #000000">;
    }
    
    </span><span style="color: #008000">/**</span><span style="color: #008000">
     * 添加接收对象的处理对象。
     * </span><span style="color: #808080">@param</span><span style="color: #008000"> cls 待处理的对象,其所属的类。
     * </span><span style="color: #808080">@param</span><span style="color: #008000"> action 处理过程对象。
     </span><span style="color: #008000">*/</span>
    <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> addActionMap(Class&lt;Object&gt;<span style="color: #000000"> cls,ObjectAction action){
        actionMapping.put(cls, action);
    }
    
    </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> sendObject(Object obj) <span style="color: #0000ff">throws</span><span style="color: #000000"> IOException {
        ObjectOutputStream oos </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> ObjectOutputStream(socket.getOutputStream());
        oos.writeObject(obj);
        System.out.println(</span>"发送:	"+<span style="color: #000000">obj);
        oos.flush();
    }
    
    </span><span style="color: #0000ff">class</span> KeepAliveWatchDog <span style="color: #0000ff">implements</span><span style="color: #000000"> Runnable{
        </span><span style="color: #0000ff">long</span> checkDelay = 10<span style="color: #000000">;
        </span><span style="color: #0000ff">long</span> keepAliveDelay = 2000<span style="color: #000000">;
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {
            </span><span style="color: #0000ff">while</span><span style="color: #000000">(running){
                </span><span style="color: #0000ff">if</span>(System.currentTimeMillis()-lastSendTime&gt;<span style="color: #000000">keepAliveDelay){
                    </span><span style="color: #0000ff">try</span><span style="color: #000000"> {
                        Client.</span><span style="color: #0000ff">this</span>.sendObject(<span style="color: #0000ff">new</span><span style="color: #000000"> KeepAlive());
                    } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (IOException e) {
                        e.printStackTrace();
                        Client.</span><span style="color: #0000ff">this</span><span style="color: #000000">.stop();
                    }
                    lastSendTime </span>=<span style="color: #000000"> System.currentTimeMillis();
                }</span><span style="color: #0000ff">else</span><span style="color: #000000">{
                    </span><span style="color: #0000ff">try</span><span style="color: #000000"> {
                        Thread.sleep(checkDelay);
                    } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {
                        e.printStackTrace();
                        Client.</span><span style="color: #0000ff">this</span><span style="color: #000000">.stop();
                    }
                }
            }
        }
    }
    
    </span><span style="color: #0000ff">class</span> ReceiveWatchDog <span style="color: #0000ff">implements</span><span style="color: #000000"> Runnable{
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {
            </span><span style="color: #0000ff">while</span><span style="color: #000000">(running){
                </span><span style="color: #0000ff">try</span><span style="color: #000000"> {
                    InputStream in </span>=<span style="color: #000000"> socket.getInputStream();
                    </span><span style="color: #0000ff">if</span>(in.available()&gt;0<span style="color: #000000">){
                        ObjectInputStream ois </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> ObjectInputStream(in);
                        Object obj </span>=<span style="color: #000000"> ois.readObject();
                        System.out.println(</span>"接收:	"+<span style="color: #000000">obj);
                        ObjectAction oa </span>=<span style="color: #000000"> actionMapping.get(obj.getClass());
                        oa </span>= oa==<span style="color: #0000ff">null</span>?<span style="color: #0000ff">new</span><span style="color: #000000"> DefaultObjectAction():oa;
                        oa.doAction(obj, Client.</span><span style="color: #0000ff">this</span><span style="color: #000000">);
                    }</span><span style="color: #0000ff">else</span><span style="color: #000000">{
                        Thread.sleep(</span>10<span style="color: #000000">);
                    }
                } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (Exception e) {
                    e.printStackTrace();
                    Client.</span><span style="color: #0000ff">this</span><span style="color: #000000">.stop();
                } 
            }
        }
    }
    

    }

    复制代码

    服务短的代码:

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

    }

    复制代码
  • 相关阅读:
    【随感】我真的很敬重你,只是你不知道。。。。。
    【diary】智慧的贪婪
    【随感】看老科和当当的回眸相视
    【转载】清华毕业致辞:从容行走于无人知晓的荒原,欣赏并创造别样的风景
    【随感】不要以为自己不足轻重而放任自己做一些事或一些话。你的不在意,才会影响到别人也不在意你。
    【随感】我觉得,世界上最美好的乐器是钢琴和架子鼓
    【技术】HTML5 canvas clock(1)
    【随感】youngLaker,fighting!
    转发公司招聘
    DBCC DBREINDEX
  • 原文地址:https://www.cnblogs.com/jpfss/p/9876282.html
Copyright © 2020-2023  润新知