• JAVA长连接demo


    [java] view plain copy
     
    1. package houlei.csdn.keepalive;  
    2.   
    3. import java.io.Serializable;  
    4. import java.text.SimpleDateFormat;  
    5. import java.util.Date;  
    6.   
    7. /** 
    8.  * 维持连接的消息对象。 
    9.  * <p> 
    10.  * 创建时间:2010-7-18 上午12:22:09 
    11.  * @author HouLei 
    12.  * @since 1.0 
    13.  */  
    14. public class KeepAlive implements Serializable{  
    15.   
    16.     private static final long serialVersionUID = -2813120366138988480L;  
    17.   
    18.     /* 覆盖该方法,仅用于测试使用。 
    19.      * @see java.lang.Object#toString() 
    20.      */  
    21.     @Override  
    22.     public String toString() {  
    23.         return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+" 维持连接包";  
    24.     }  
    25.   
    26. }  
    [java] view plain copy
     
    1. package houlei.csdn.keepalive;  
    2.   
    3. import java.io.IOException;  
    4. import java.io.InputStream;  
    5. import java.io.ObjectInputStream;  
    6. import java.io.ObjectOutputStream;  
    7. import java.net.Socket;  
    8. import java.net.UnknownHostException;  
    9. import java.util.concurrent.ConcurrentHashMap;  
    10.   
    11. /** 
    12.  *  C/S架构的客户端对象,持有该对象,可以随时向服务端发送消息。 
    13.  * <p> 
    14.  * 创建时间:2010-7-18 上午12:17:25 
    15.  * @author HouLei 
    16.  * @since 1.0 
    17.  */  
    18. public class Client {  
    19.   
    20.     /** 
    21.      * 处理服务端发回的对象,可实现该接口。 
    22.      */  
    23.     public static interface ObjectAction{  
    24.         void doAction(Object obj,Client client);  
    25.     }  
    26.     public static final class DefaultObjectAction implements ObjectAction{  
    27.         public void doAction(Object obj,Client client) {  
    28.             System.out.println("处理: "+obj.toString());  
    29.         }  
    30.     }  
    31.     public static void main(String[] args) throws UnknownHostException, IOException {  
    32.         String serverIp = "127.0.0.1";  
    33.         int port = 65432;  
    34.         Client client = new Client(serverIp,port);  
    35.         client.start();  
    36.     }  
    37.       
    38.     private String serverIp;  
    39.     private int port;  
    40.     private Socket socket;  
    41.     private boolean running=false;  
    42.     private long lastSendTime;  
    43.     private ConcurrentHashMap<Class, ObjectAction> actionMapping = new ConcurrentHashMap<Class,ObjectAction>();  
    44.       
    45.     public Client(String serverIp, int port) {  
    46.         this.serverIp=serverIp;this.port=port;  
    47.     }  
    48.       
    49.     public void start() throws UnknownHostException, IOException {  
    50.         if(running)return;  
    51.         socket = new Socket(serverIp,port);  
    52.         System.out.println("本地端口:"+socket.getLocalPort());  
    53.         lastSendTime=System.currentTimeMillis();  
    54.         running=true;  
    55.         new Thread(new KeepAliveWatchDog()).start();  
    56.         new Thread(new ReceiveWatchDog()).start();  
    57.     }  
    58.       
    59.     public void stop(){  
    60.         if(running)running=false;  
    61.     }  
    62.       
    63.     /** 
    64.      * 添加接收对象的处理对象。 
    65.      * @param cls 待处理的对象,其所属的类。 
    66.      * @param action 处理过程对象。 
    67.      */  
    68.     public void addActionMap(Class<Object> cls,ObjectAction action){  
    69.         actionMapping.put(cls, action);  
    70.     }  
    71.   
    72.     public void sendObject(Object obj) throws IOException {  
    73.         ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());  
    74.         oos.writeObject(obj);  
    75.         System.out.println("发送: "+obj);  
    76.         oos.flush();  
    77.     }  
    78.       
    79.     class KeepAliveWatchDog implements Runnable{  
    80.         long checkDelay = 10;  
    81.         long keepAliveDelay = 2000;  
    82.         public void run() {  
    83.             while(running){  
    84.                 if(System.currentTimeMillis()-lastSendTime>keepAliveDelay){  
    85.                     try {  
    86.                         Client.this.sendObject(new KeepAlive());  
    87.                     } catch (IOException e) {  
    88.                         e.printStackTrace();  
    89.                         Client.this.stop();  
    90.                     }  
    91.                     lastSendTime = System.currentTimeMillis();  
    92.                 }else{  
    93.                     try {  
    94.                         Thread.sleep(checkDelay);  
    95.                     } catch (InterruptedException e) {  
    96.                         e.printStackTrace();  
    97.                         Client.this.stop();  
    98.                     }  
    99.                 }  
    100.             }  
    101.         }  
    102.     }  
    103.       
    104.     class ReceiveWatchDog implements Runnable{  
    105.         public void run() {  
    106.             while(running){  
    107.                 try {  
    108.                     InputStream in = socket.getInputStream();  
    109.                     if(in.available()>0){  
    110.                         ObjectInputStream ois = new ObjectInputStream(in);  
    111.                         Object obj = ois.readObject();  
    112.                         System.out.println("接收: "+obj);  
    113.                         ObjectAction oa = actionMapping.get(obj.getClass());  
    114.                         oa = oa==null?new DefaultObjectAction():oa;  
    115.                         oa.doAction(obj, Client.this);  
    116.                     }else{  
    117.                         Thread.sleep(10);  
    118.                     }  
    119.                 } catch (Exception e) {  
    120.                     e.printStackTrace();  
    121.                     Client.this.stop();  
    122.                 }   
    123.             }  
    124.         }  
    125.     }  
    126.       
    127. }  
    [java] view plain copy
     
    1. package houlei.csdn.keepalive;  
    2.   
    3.   
    4. import java.io.IOException;  
    5. import java.io.InputStream;  
    6. import java.io.ObjectInputStream;  
    7. import java.io.ObjectOutputStream;  
    8. import java.net.ServerSocket;  
    9. import java.net.Socket;  
    10. import java.util.concurrent.ConcurrentHashMap;  
    11.   
    12. /** 
    13.  * C/S架构的服务端对象。 
    14.  * <p> 
    15.  * 创建时间:2010-7-18 上午12:17:37 
    16.  * @author HouLei 
    17.  * @since 1.0 
    18.  */  
    19. public class Server {  
    20.   
    21.     /** 
    22.      * 要处理客户端发来的对象,并返回一个对象,可实现该接口。 
    23.      */  
    24.     public interface ObjectAction{  
    25.         Object doAction(Object rev);  
    26.     }  
    27.       
    28.     public static final class DefaultObjectAction implements ObjectAction{  
    29.         public Object doAction(Object rev) {  
    30.             System.out.println("处理并返回:"+rev);  
    31.             return rev;  
    32.         }  
    33.     }  
    34.       
    35.     public static void main(String[] args) {  
    36.         int port = 65432;  
    37.         Server server = new Server(port);  
    38.         server.start();  
    39.     }  
    40.       
    41.     private int port;  
    42.     private volatile boolean running=false;  
    43.     private long receiveTimeDelay=3000;  
    44.     private ConcurrentHashMap<Class, ObjectAction> actionMapping = new ConcurrentHashMap<Class,ObjectAction>();  
    45.     private Thread connWatchDog;  
    46.       
    47.     public Server(int port) {  
    48.         this.port = port;  
    49.     }  
    50.   
    51.     public void start(){  
    52.         if(running)return;  
    53.         running=true;  
    54.         connWatchDog = new Thread(new ConnWatchDog());  
    55.         connWatchDog.start();  
    56.     }  
    57.       
    58.     @SuppressWarnings("deprecation")  
    59.     public void stop(){  
    60.         if(running)running=false;  
    61.         if(connWatchDog!=null)connWatchDog.stop();  
    62.     }  
    63.       
    64.     public void addActionMap(Class<Object> cls,ObjectAction action){  
    65.         actionMapping.put(cls, action);  
    66.     }  
    67.       
    68.     class ConnWatchDog implements Runnable{  
    69.         public void run(){  
    70.             try {  
    71.                 ServerSocket ss = new ServerSocket(port,5);  
    72.                 while(running){  
    73.                     Socket s = ss.accept();  
    74.                     new Thread(new SocketAction(s)).start();  
    75.                 }  
    76.             } catch (IOException e) {  
    77.                 e.printStackTrace();  
    78.                 Server.this.stop();  
    79.             }  
    80.               
    81.         }  
    82.     }  
    83.       
    84.     class SocketAction implements Runnable{  
    85.         Socket s;  
    86.         boolean run=true;  
    87.         long lastReceiveTime = System.currentTimeMillis();  
    88.         public SocketAction(Socket s) {  
    89.             this.s = s;  
    90.         }  
    91.         public void run() {  
    92.             while(running && run){  
    93.                 if(System.currentTimeMillis()-lastReceiveTime>receiveTimeDelay){  
    94.                     overThis();  
    95.                 }else{  
    96.                     try {  
    97.                         InputStream in = s.getInputStream();  
    98.                         if(in.available()>0){  
    99.                             ObjectInputStream ois = new ObjectInputStream(in);  
    100.                             Object obj = ois.readObject();  
    101.                             lastReceiveTime = System.currentTimeMillis();  
    102.                             System.out.println("接收: "+obj);  
    103.                             ObjectAction oa = actionMapping.get(obj.getClass());  
    104.                             oa = oa==null?new DefaultObjectAction():oa;  
    105.                             Object out = oa.doAction(obj);  
    106.                             if(out!=null){  
    107.                                 ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());  
    108.                                 oos.writeObject(out);  
    109.                                 oos.flush();  
    110.                             }  
    111.                         }else{  
    112.                             Thread.sleep(10);  
    113.                         }  
    114.                     } catch (Exception e) {  
    115.                         e.printStackTrace();  
    116.                         overThis();  
    117.                     }   
    118.                 }  
    119.             }  
    120.         }  
    121.           
    122.         private void overThis() {  
    123.             if(run)run=false;  
    124.             if(s!=null){  
    125.                 try {  
    126.                     s.close();  
    127.                 } catch (IOException e) {  
    128.                     e.printStackTrace();  
    129.                 }  
    130.             }  
    131.             System.out.println("关闭:"+s.getRemoteSocketAddress());  
    132.         }  
    133.           
    134.     }  
    135.       
    136. }  


    大致解释一下什么意思:

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

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

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

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

  • 相关阅读:
    Linux let 命令
    perl hash array 嵌套 push
    Perl CGI编程
    Perl关联数组用法集锦
    关于反射和动态代理
    SpringBoot与web开发
    Springboot与日志
    Spring Boot
    SpringBoot的自动配置原理
    Spring MVC执行流程
  • 原文地址:https://www.cnblogs.com/austinspark-jessylu/p/7323742.html
Copyright © 2020-2023  润新知