如何干净的实现Android/Java Socket 长连接通信

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何干净的实现Android/Java Socket 长连接通信相关的知识,希望对你有一定的参考价值。

所谓长连接,它通常包含以下几个关键过程:

    轮询的建立        
    建立轮询的过程很简单,浏览器发起请求后进入循环等待状态,此时由于服务器还未做出应答,所以HTTP也一直处于连接状态中。        
    2. 数据的推送        
    在循环过程中,服务器程序对数据变动进行监控,如发现更新,将该信息输出给浏览器,随即断开连接,完成应答过程,实现“服务器推”。        
    3. 轮询的终止        
    轮询可能在以下3种情况时终止:        
      3.1. 有新数据推送        
       当循环过程中服务器向浏览器推送信息后,应该主动结束程序运行从而让连接断开,这样浏览器才能及时收到数据。        
      3.2. 没有新数据推送        
       循环不能一直持续下去,应该设定一个最长时限,避免WEB服务器超时(Timeout),若一直没有新信息,服务器应主动向浏览器发送本次轮询无新信息的正常响应,并断开连接,这也被称为“心跳”信息。        
      3.3. 网络故障或异常        
       由于网络故障等因素造成的请求超时或出错也可能导致轮询的意外中断,此时浏览器将收到错误信息。        
    4. 轮询的重建        
    浏览器收到回复并进行相应处理后,应马上重新发起请求,开始一个新的轮询周期。

客户端代码片段

                  <%@ page language="java" import="java.util.*" pageEncoding="UTF-8" isELIgnored="false" %>



     <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">



     <html>



         <head>



             <meta http-equiv="pragma" content="no-cache">



             <meta http-equiv="cache-control" content="no-cache">



             <meta http-equiv="author" content="hoojo & http://hoojo.cnblogs.com">



             <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />



             <%@ include file="/tags/jquery-lib.jsp"%>



             



             <script type="text/javascript">



                 $(function ()



                 



                     window.setInterval(function ()



                     



                         $.get("$pageContext.request.contextPath/communication/user/ajax.mvc",



                             "timed": new Date().getTime(),



                             function (data)



                                 $("#logs").append("[data: " + data + " ]<br/>");



                         );



                     , 3000);



                     



                 );



             </script>



         </head>



         



         <body>



             <div id="logs"></div>



         </body>



     </html>

服务器端代码

   

   

   
     @RequestMapping("/ajax")



     public void ajax(long timed, HttpServletResponse response) throws Exception



          PrintWriter writer = response.getWriter();



         



          Random rand = new Random();



          // 死循环 查询有无数据变化



          while (true)



              Thread.sleep(300); // 休眠300毫秒,模拟处理业务等



              int i = rand.nextInt(100); // 产生一个0-100之间的随机数



              if (i > 20 && i < 56) // 如果随机数在20-56之间就视为有效数据,模拟数据发生变化



                  long responseTime = System.currentTimeMillis();



                  // 返回数据信息,请求时间、返回数据时间、耗时



                  writer.print("result: " + i + ", response time: " + responseTime + ", request time: " + timed + ", use time: " + (responseTime - timed));



                  break; // 跳出循环,返回数据



              else // 模拟没有数据变化,将休眠 hold住连接



                  Thread.sleep(1300);



             



         



         



     

参考技术A   现编这个就是个多线程服务器,只要在client不释放连接,服务器端的run里边写while(TRUE)循环,那么就可以长期连接。
  class ConnectionThread extends Thread
  Socket client;
  int counter;
  public ConnectionThread(Socket cl,int c)
  client = cl;
  counter= c;
  
  @Override
  public void run()
  
  try
  String destIP=client.getInetAddress().toString();
  int destport =client.getPort();
  PrintStream outstream=new PrintStream(client.getOutputStream());
  DataInputStream instream=new DataInputStream(client.getInputStream());
  String inline=instream.readLine();
  //try
  catch(IOException e)System.out.println(e);
  //run本回答被提问者采纳
参考技术B 看你用什么协议

Tomcat 上的 Websockets:如何干净地关闭服务器?

【中文标题】Tomcat 上的 Websockets:如何干净地关闭服务器?【英文标题】:Websockets on Tomcat: how to shutdown the server cleanly? 【发布时间】:2015-08-07 08:35:37 【问题描述】:

如何拦截服务器上运行的端点的关闭事件(例如 servlet 的销毁方法)以用于日志记录或其他目的?

【问题讨论】:

你找到答案了吗? 【参考方案1】:

Spring 4 Java 配置:

实现 SmartLifecycle(使用基于 Java 的配置时,或将 Java 代码转换为 XML):

@Configuration
public class CycleBean implements SmartLifecycle 

    public CycleBean() 
    

    @Override
    public boolean isRunning() 
        return true;
    

    @Override
    public void start() 
    

    @Override
    public void stop() 
        //when stopped call 
    

    @Override
    public int getPhase() 
        return 0;
    

    @Override
    public boolean isAutoStartup() 
        return true;
    

    @Override
    public void stop(Runnable arg0) 
        //
    

见http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html第4.6段自定义bean的性质,如:

<bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor">
  <!-- timeout value in milliseconds -->
  <property name="timeoutPerShutdownPhase" value="10000"/>
</bean>

【讨论】:

感谢您的快速回复。但是我的上下文没有 spring 框架,只有一个在 Tomcat webapp 中运行的 EndPoint。 不好意思,我没听说过EndPoint 所以没把它当成环境 顺便说一句,我拼错了:我应该写 Endpoint http://docs.oracle.com/javaee/7/api/javax/websocket/Endpoint.html 但是...我会说覆盖onClose(Session session, EndpointConfig config) 方法。首先(如果可能)调用super.onClose(session, closeReason),然后调用日志记录方法 谢谢丹尼尔森。但是,onClose(Session session, CloseReason reason) 方法是为每个关闭的会话触发的,而不是在端点实例关闭时触发。而且我找不到方法onClose(Session session, EndpointConfig config) 来覆盖...它应该属于哪个类?

以上是关于如何干净的实现Android/Java Socket 长连接通信的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android 中干净地叠加 ScrollableViews

java 网络编程中 tcp连接问题。 例如编写聊天室 , c/s结构的c和s端都是不间断实现请求--响应 。

httpclient 怎么实现多文件上传 c/s java

java如何在传输文件时显示传输速度,比如:100kb/s。一点头绪都没有,请大家帮帮看看吧,越详细越好。

干净的架构。主持人的工作是啥?

有一存储过程,里面实现了增删改查,我如何在C/S界面中,事件中调用此存储过程,举例说明,求高手解答!