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())+"\t維持連接包";  
  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("處理:\t"+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("發送:\t"+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("接收:\t"+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("接收:\t"+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實現類,可以實現不同對象的響應、應答過程。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM