欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于心跳的socket长连接

程序员文章站 2022-06-17 19:30:18
...

案例: 
心跳: 
socket模拟网页的报文连接某个网站,创建tcp的socket后,当我socket.connect后,如果在5到7秒钟不socket.send,那么这个链接就失效了。 请问如何长时间的保持这个链接 
这是在服务器端的设置的,客户端没法设置,可以发送心跳包。 
socket.connect后,每3-4秒用socket.send发送一字节数据(内容随便),然后观查这个连接是否保持。 

lientSocket=serverSocket.accept(); 
OutputStream os = clientSocket.getOutputStream();           
ObjectOutputStream oos=new ObjectOutputStream(os); 
oos.writeObject(al); 
oos.flush(); 
oos.close()//socket会关闭 

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

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

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


Java代码   基于心跳的socket长连接
            
    
    博客分类: JAVA socket 
  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.  */  
  10. public class KeepAlive implements Serializable{  
  11.   
  12.     private static final long serialVersionUID = -2813120366138988480L;  
  13.   
  14.     /* 覆盖该方法,仅用于测试使用。 
  15.      * @see java.lang.Object#toString() 
  16.      */  
  17.     @Override  
  18.     public String toString() {  
  19.         return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"\t维持连接包";  
  20.     }  
  21.   
  22. }  



client: 

Java代码   基于心跳的socket长连接
            
    
    博客分类: JAVA socket 
  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.  */  
  14. public class Client {  
  15.   
  16.     /** 
  17.      * 处理服务端发回的对象,可实现该接口。 
  18.      */  
  19.     public static interface ObjectAction{  
  20.         void doAction(Object obj,Client client);  
  21.     }  
  22.     public static final class DefaultObjectAction implements ObjectAction{  
  23.         public void doAction(Object obj,Client client) {  
  24.             System.out.println("处理:\t"+obj.toString());  
  25.         }  
  26.     }  
  27.     public static void main(String[] args) throws UnknownHostException, IOException {  
  28.         String serverIp = "127.0.0.1";  
  29.         int port = 65432;  
  30.         Client client = new Client(serverIp,port);  
  31.         client.start();  
  32.     }  
  33.       
  34.     private String serverIp;  
  35.     private int port;  
  36.     private Socket socket;  
  37.     private boolean running=false;  
  38.     private long lastSendTime;  
  39.     private ConcurrentHashMap<Class, ObjectAction> actionMapping = new ConcurrentHashMap<Class,ObjectAction>();  
  40.       
  41.     public Client(String serverIp, int port) {  
  42.         this.serverIp=serverIp;this.port=port;  
  43.     }  
  44.       
  45.     public void start() throws UnknownHostException, IOException {  
  46.         if(running)return;  
  47.         socket = new Socket(serverIp,port);  
  48.         System.out.println("本地端口:"+socket.getLocalPort());  
  49.         lastSendTime=System.currentTimeMillis();  
  50.         running=true;  
  51.         new Thread(new KeepAliveWatchDog()).start();  
  52.         new Thread(new ReceiveWatchDog()).start();  
  53.     }  
  54.       
  55.     public void stop(){  
  56.         if(running)running=false;  
  57.     }  
  58.       
  59.     /** 
  60.      * 添加接收对象的处理对象。 
  61.      * @param cls 待处理的对象,其所属的类。 
  62.      * @param action 处理过程对象。 
  63.      */  
  64.     public void addActionMap(Class<Object> cls,ObjectAction action){  
  65.         actionMapping.put(cls, action);  
  66.     }  
  67.   
  68.     public void sendObject(Object obj) throws IOException {  
  69.         ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());  
  70.         oos.writeObject(obj);  
  71.         System.out.println("发送:\t"+obj);  
  72.         oos.flush();  
  73.     }  
  74.       
  75.     class KeepAliveWatchDog implements Runnable{  
  76.         long checkDelay = 10;  
  77.         long keepAliveDelay = 2000;  
  78.         public void run() {  
  79.             while(running){  
  80.                 if(System.currentTimeMillis()-lastSendTime>keepAliveDelay){  
  81.                     try {  
  82.                         Client.this.sendObject(new KeepAlive());  
  83.                     } catch (IOException e) {  
  84.                         e.printStackTrace();  
  85.                         Client.this.stop();  
  86.                     }  
  87.                     lastSendTime = System.currentTimeMillis();  
  88.                 }else{  
  89.                     try {  
  90.                         Thread.sleep(checkDelay);  
  91.                     } catch (InterruptedException e) {  
  92.                         e.printStackTrace();  
  93.                         Client.this.stop();  
  94.                     }  
  95.                 }  
  96.             }  
  97.         }  
  98.     }  
  99.       
  100.     class ReceiveWatchDog implements Runnable{  
  101.         public void run() {  
  102.             while(running){  
  103.                 try {  
  104.                     InputStream in = socket.getInputStream();  
  105.                     if(in.available()>0){  
  106.                         ObjectInputStream ois = new ObjectInputStream(in);  
  107.                         Object obj = ois.readObject();  
  108.                         System.out.println("接收:\t"+obj);  
  109.                         ObjectAction oa = actionMapping.get(obj.getClass());  
  110.                         oa = oa==null?new DefaultObjectAction():oa;  
  111.                         oa.doAction(obj, Client.this);  
  112.                     }else{  
  113.                         Thread.sleep(10);  
  114.                     }  
  115.                 } catch (Exception e) {  
  116.                     e.printStackTrace();  
  117.                     Client.this.stop();  
  118.                 }   
  119.             }  
  120.         }  
  121.     }  
  122.       
  123. }  



server: 

Java代码   基于心跳的socket长连接
            
    
    博客分类: JAVA socket 
  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.  */  
  15. public class Server {  
  16.   
  17.     /** 
  18.      * 要处理客户端发来的对象,并返回一个对象,可实现该接口。 
  19.      */  
  20.     public interface ObjectAction{  
  21.         Object doAction(Object rev);  
  22.     }  
  23.       
  24.     public static final class DefaultObjectAction implements ObjectAction{  
  25.         public Object doAction(Object rev) {  
  26.             System.out.println("处理并返回:"+rev);  
  27.             return rev;  
  28.         }  
  29.     }  
  30.       
  31.     public static void main(String[] args) {  
  32.         int port = 65432;  
  33.         Server server = new Server(port);  
  34.         server.start();  
  35.     }  
  36.       
  37.     private int port;  
  38.     private volatile boolean running=false;  
  39.     private long receiveTimeDelay=3000;  
  40.     private ConcurrentHashMap<Class, ObjectAction> actionMapping = new ConcurrentHashMap<Class,ObjectAction>();  
  41.     private Thread connWatchDog;  
  42.       
  43.     public Server(int port) {  
  44.         this.port = port;  
  45.     }  
  46.   
  47.     public void start(){  
  48.         if(running)return;  
  49.         running=true;  
  50.         connWatchDog = new Thread(new ConnWatchDog());  
  51.         connWatchDog.start();  
  52.     }  
  53.       
  54.     @SuppressWarnings("deprecation")  
  55.     public void stop(){  
  56.         if(running)running=false;  
  57.         if(connWatchDog!=null)connWatchDog.stop();  
  58.     }  
  59.       
  60.     public void addActionMap(Class<Object> cls,ObjectAction action){  
  61.         actionMapping.put(cls, action);  
  62.     }  
  63.       
  64.     class ConnWatchDog implements Runnable{  
  65.         public void run(){  
  66.             try {  
  67.                 ServerSocket ss = new ServerSocket(port,5);  
  68.                 while(running){  
  69.                     Socket s = ss.accept();  
  70.                     new Thread(new SocketAction(s)).start();  
  71.                 }  
  72.             } catch (IOException e) {  
  73.                 e.printStackTrace();  
  74.                 Server.this.stop();  
  75.             }  
  76.               
  77.         }  
  78.     }  
  79.       
  80.     class SocketAction implements Runnable{  
  81.         Socket s;  
  82.         boolean run=true;  
  83.         long lastReceiveTime = System.currentTimeMillis();  
  84.         public SocketAction(Socket s) {  
  85.             this.s = s;  
  86.         }  
  87.         public void run() {  
  88.             while(running && run){  
  89.                 if(System.currentTimeMillis()-lastReceiveTime>receiveTimeDelay){  
  90.                     overThis();  
  91.                 }else{  
  92.                     try {  
  93.                         InputStream in = s.getInputStream();  
  94.                         if(in.available()>0){  
  95.                             ObjectInputStream ois = new ObjectInputStream(in);  
  96.                             Object obj = ois.readObject();  
  97.                             lastReceiveTime = System.currentTimeMillis();  
  98.                             System.out.println("接收:\t"+obj);  
  99.                             ObjectAction oa = actionMapping.get(obj.getClass());  
  100.                             oa = oa==null?new DefaultObjectAction():oa;  
  101.                             Object out = oa.doAction(obj);  
  102.                             if(out!=null){  
  103.                                 ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());  
  104.                                 oos.writeObject(out);  
  105.                                 oos.flush();  
  106.                             }  
  107.                         }else{  
  108.                             Thread.sleep(10);  
  109.                         }  
  110.                     } catch (Exception e) {  
  111.                         e.printStackTrace();  
  112.                         overThis();  
  113.                     }   
  114.                 }  
  115.             }  
  116.         }  
  117.           
  118.         private void overThis() {  
  119.             if(run)run=false;  
  120.             if(s!=null){  
  121.                 try {  
  122.                     s.close();  
  123.                 } catch (IOException e) {  
  124.                     e.printStackTrace();  
  125.                 }  
  126.             }  
  127.             System.out.println("关闭:"+s.getRemoteSocketAddress());  
  128.         }  
  129.           
  130.     }  
  131.       
  132. }  
  133.   转载自:http://coach.iteye.com/blog/2024444
相关标签: socket