jslfl 发表于 2013-1-23 01:20:39

WebIM

WebIM开发技术细节
最近两年WebIM特别的流行,像淘宝的阿里旺旺网页版,腾讯的WEBQQ,Google的gtalk,百度hi等等都陆续推出了自己的网页版的聊天软件。实现网页的即时聊天,有一个关键的问题就是怎么样让服务器不停的往客户度发送数据,现在解决的方案一般是用:iframe 隐藏帧,flash的xmlsocket,或者使用ajax在请求未结束的时候马上发起请求。我个人觉得还是iframe的实现方式比较好,目前腾讯等都是用的iframe的方式,具体原因不解释。但是对于iframe如何传送数据是一个难点。突破这个难点一切就简单了。

我自己参考了一些博客资料以及国外的完整后自己测试终于把这个问题给解决了,要让服务端一直发送数据首先要利用chunked传输response。

下面列出我的实现代码:



XML/HTML代码1.<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2.<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
3.<html>
4.<head>      
5.    <title>Iframe数据</title>
6.    <meta http-equiv="pragma" content="no-cache">
7.    <meta http-equiv="cache-control" content="no-cache">
8.    <meta http-equiv="expires" content="0">      
9.    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>   
10.</head>
11.<body>
12.    数据列表:<br/>
13.    <div id="datalist" style="width:400px;height:300px;border:1px solid #EF0;overflow: auto;">
14.      
15.    </div>
16.    <script type="text/javascript">
17.      function getData(d){   
18.            $("#datalist").append(d);   
19.      }   
20.      function rpc_iframe() {   
21.            var transferDoc = new ActiveXObject("htmlfile");   
22.            transferDoc.open();   
23.            transferDoc.write("<html>")   
24.            transferDoc.write("<div><iframe src=\"IFrameStream.do\"></iframe></div>");   
25.            transferDoc.close("</html>");   
26.            transferDoc.parentWindow.getData = getData;   
27.            setInterval(function () { }, 10000);//不加这句会使连接断开   
28.      }   
29.      rpc_iframe();   
30.    </script>
31.      
32.</body>
33.</html>
接下来是我们后台的代码:



Java代码1.package org.javafans.chat;   
2.
3.import java.io.IOException;   
4.import java.io.PrintWriter;   
5.import java.text.SimpleDateFormat;   
6.import java.util.Date;   
7.
8.import javax.servlet.ServletException;   
9.import javax.servlet.annotation.WebServlet;   
10.import javax.servlet.http.HttpServlet;   
11.import javax.servlet.http.HttpServletRequest;   
12.import javax.servlet.http.HttpServletResponse;   
13.
14.@WebServlet(urlPatterns="/IFrameStream.do")   
15.public class IFrameStreamServlet extends HttpServlet{   
16.    /**
17.   * @Fields serialVersionUID : TODO(用一句话描述这个变量表示什么)   
18.   */
19.    private static final long serialVersionUID = 1L;   
20.
21.    /* (non-Javadoc)
22.   * <p>Title: doGet</p>   
23.   * <p>Description: </p>   
24.   * @param req
25.   * @param resp
26.   * @throws ServletException
27.   * @throws IOException
28.   * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
29.   */
30.    @Override
31.    protected void doGet(HttpServletRequest req, HttpServletResponse resp)   
32.      throws ServletException, IOException {   
33.    // TODO Auto-generated method stub   
34.    this.doPost(req, resp);   
35.    }   
36.
37.    /* (non-Javadoc)
38.   * <p>Title: doPost</p>   
39.   * <p>Description: </p>   
40.   * @param req
41.   * @param resp
42.   * @throws ServletException
43.   * @throws IOException
44.   * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
45.   */
46.    @Override
47.    protected void doPost(HttpServletRequest req, HttpServletResponse resp)   
48.      throws ServletException, IOException {   
49.    // TODO Auto-generated method stub   
50.      
51.    //需要实时生成消息长度,服务器一般使用chunked编码。   
52.    resp.setHeader("transfer-coding", "chunked");   
53.    resp.setContentType("text/html;charset=utf8");   
54.    PrintWriter out = resp.getWriter();   
55.      
56.    String startHTML = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\r\n";   
57.    startHTML += "<html xmlns=\"http://www.w3.org/1999/xhtml\" >\r\n" ;   
58.    startHTML += "<head>\r\n</head>\r\n" ;   
59.    startHTML += "<body>\r\n" ;   
60.      
61.    out.write(startHTML);   
62.    out.flush();   
63.      
64.    String data = "<script type=\"text/javascript\">parent.getData(\"%s\");</script>";   
65.      
66.    out.write(String.format(data, "开始发送数据<br/>"));   
67.    out.flush();   
68.    while(true){   
69.      try {   
70.      Thread.sleep(1000);   
71.      } catch (InterruptedException e) {   
72.      e.printStackTrace();   
73.      }   
74.      out.append(String.format(data,"服务端发送的数据"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"<br/>"));   
75.      out.flush();   
76.    }   
77.      
78.      
79.    }   
80.
81.      
82.      
83.}
页: [1]
查看完整版本: WebIM