如何实现java http长连接推送数据

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何实现java http长连接推送数据相关的知识,希望对你有一定的参考价值。

Feign在默认情况下使用的是JDK原生的URLConnection发送HTTP请求,没有连接池,但是对每个地址会保持一个长连接,即利用HTTP的persistence connection 。我们可以用Apache的HTTP Client替换Feign原始的http client, 从而获取连接池、超时时间等与性能息息相关的控制能力。Spring Cloud从Brixtion.SR5版本开始支持这种替换,首先在项目中声明Apache HTTP Client和feign-httpclient依赖 参考技术A Feign在默认情况下使用的是JDK原生的URLConnection发送HTTP请求,没有连接池,但是对每个地址会保持一个长连接,即利用HTTP的persistence connection 。我们可以用Apache的HTTP Client替换Feign原始的http client, 从而获取连接池、超时时间等与性能息息相关的控制能力。Spring Cloud从Brixtion.SR5版本开始支持这种替换,首先在项目中声明Apache HTTP Client和feign-httpclient依赖 参考技术B 通过轮询来实现长连接
轮询:隔一段时间访问服务器,服务器不管有没有新消息都立刻返回。
http长连接实现代码:
客户端:
package houlei.csdn.keepalive;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.ConcurrentHashMap;

/**
* C/S架构的客户端对象,持有该对象,可以随时向服务端发送消息。
* <p>
* 创建时间:2010-7-18 上午12:17:25
* @author HouLei
* @since 1.0
*/
public class Client

/**
* 处理服务端发回的对象,可实现该接口。
*/
public static interface ObjectAction
void doAction(Object obj,Client client);

public static final class DefaultObjectAction implements ObjectAction
public void doAction(Object obj,Client client)
System.out.println("处理:\t"+obj.toString());//诊断程序是否正常


public static void main(String[] args) throws UnknownHostException, IOException
String serverIp = "127.0.0.1";
int port = 65432;
Client client = new Client(serverIp,port);
client.start();


private String serverIp;
private int port;
private Socket socket;
private boolean running=false;
private long lastSendTime;
private ConcurrentHashMap<Class, ObjectAction> actionMapping = new ConcurrentHashMap<Class,ObjectAction>();

public Client(String serverIp, int port)
this.serverIp=serverIp;this.port=port;


public void start() throws UnknownHostException, IOException
if(running)return;
socket = new Socket(serverIp,port);
System.out.println("本地端口:"+socket.getLocalPort());
lastSendTime=System.currentTimeMillis();
running=true;
new Thread(new KeepAliveWatchDog()).start();
new Thread(new ReceiveWatchDog()).start();


public void stop()
if(running)running=false;


/**
* 添加接收对象的处理对象。
* @param cls 待处理的对象,其所属的类。
* @param action 处理过程对象。
*/
public void addActionMap(Class<Object> cls,ObjectAction action)
actionMapping.put(cls, action);


public void sendObject(Object obj) throws IOException
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(obj);
System.out.println("发送:\t"+obj);
oos.flush();


class KeepAliveWatchDog implements Runnable
long checkDelay = 10;
long keepAliveDelay = 2000;
public void run()
while(running)
if(System.currentTimeMillis()-lastSendTime>keepAliveDelay)
try
Client.this.sendObject(new KeepAlive());
catch (IOException e)
e.printStackTrace();
Client.this.stop();

lastSendTime = System.currentTimeMillis();本回答被提问者采纳

如何干净的实现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 看你用什么协议

以上是关于如何实现java http长连接推送数据的主要内容,如果未能解决你的问题,请参考以下文章

android怎么实现HTTP长连接

Netty 长连接 Server 主动推送功能实现及问题

利用Jquery实现http长连接(LongPoll)

java 怎么实现http1.1中规定的pipeline的长连接

用 servlet实现http长连接

HTTP长连接是啥?底层是如何工作的?Tomcat是如何实现长连接的?