java 实现长链接Comet

测试环境Tomcat7

Servlet3以后才支持异步Servlet, Tomcat7中才支持. 其他jsp服务器没有测试.

1. Servlet

View Code
 1 import java.io.IOException;
 2 import java.util.Enumeration;
 3 import java.util.UUID;
 4 
 5 import javax.servlet.ServletException;
 6 import javax.servlet.http.HttpServlet;
 7 import javax.servlet.http.HttpServletRequest;
 8 import javax.servlet.http.HttpServletResponse;
 9 
10 import net.sf.json.JSONObject;
11 
12 13 14 
15 public class CometServlet extends HttpServlet {
16 
17     @Override
18     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
19             throws ServletException, IOException {
20         doPost(req, resp);
21     }
22 
23     @Override
24     protected void doPost(HttpServletRequest req, HttpServletResponse resp)
25             throws ServletException, IOException {
26         System.out.println("CometServlet" + req);
27         Object UserId = req.getSession().getAttribute("UserId");
28         if (UserId == null) {
29             UserId = UUID.randomUUID().toString();
30             req.getSession().setAttribute("UserId", UserId);
31         }
32         System.out.println("Userid=" + UserId);
33         if (!req.isAsyncStarted()) {
34             req.startAsync();
35         }
36         resp.addHeader("Connection", "keep-alive");
37         resp.addHeader("Content-Type", "text/html; charset=utf-8");
38         Enumeration<String> names = req.getParameterNames();
39 
40         JSONObject json = new JSONObject();
41         String key;
42         while (names.hasMoreElements()) {
43             key = names.nextElement();
44             json.put(key, req.getParameter(key));
45         }
46         AsynResult asynResult = new AsynResult(req.getAsyncContext(), json,
47                 UserId.toString());
48         AsynMsg.getInstance().AddClient(asynResult);
49     }
50 }

2. 同步消息缓存

View Code
 1 import javax.servlet.AsyncContext;
 2 import javax.servlet.ServletResponse;
 3 
 4 import net.sf.json.JSONObject;
 5 
 6 public class AsynResult {
 7     private AsyncContext context;
 8     private JSONObject json;
 9     private String userId;
10 
11     public AsyncContext getContext() {
12         return context;
13     }
14 
15     public JSONObject getJson() {
16         return json;
17     }
18 
19     public String getUserId() {
20         return userId;
21     }
22 
23     public AsynResult(AsyncContext context, JSONObject json, String userId) {
24         this.context = context;
25         this.json = json;
26         this.userId = userId;
27     }
28 
29     public void send(JSONObject json) {
30         try {
31             ServletResponse rep = context.getResponse();
32             rep.setContentType("application/json;charset=UTF-8");
33             rep.setCharacterEncoding("UTF-8");
34             rep.getWriter().write(json.toString());
35         } catch (Exception e) {
36         }
37     }
38 }

3. 消息处理

View Code
 1 import java.util.HashMap;
 2 import java.util.Map;
 3 
 4 import net.sf.json.JSONObject;
 5 
 6  7 
 8 public class AsynMsg {
 9     // List<AsynResult> clients = new ArrayList<AsynResult>();
10     private Map<String, AsynResult> clients = new HashMap<String, AsynResult>();
11     // region 实现该类的单例
12     private static final AsynMsg _Instance = new AsynMsg();
13     private static final String KEY = "msg";
14 
15     private AsynMsg() {
16     }
17 
18     public static AsynMsg getInstance() {
19         return _Instance;
20     }
21 
22     public void AddClient(AsynResult result) {
23         String type = result.getJson().optString("type", "data");
24         String to = result.getJson().optString("to", null);
25         String user = result.getUserId();
26         String from = user;
27 
28         if (type.equals("wait")) {
29             if("lott".equals(result.getJson().optString("msgType",""))){
30                 user = "lott";
31             }
32             clients.put(user, result);
33             try {
34                 synchronized (clients) {
35                     clients.wait();
36                 }
37             } catch (InterruptedException e) {
38                 e.printStackTrace();
39             }
40         } else {
41             if("".equals(type)){
42                 to = "lott";
43             }
44             JSONObject json = new JSONObject();
45             json.put(KEY, user + ":" + result.getJson().getString("asynMsg"));
46             // 将当前请求的内容输出到客户端
47             result.send(json);
48 
49             // 否则将遍历所有已缓存的client,并将当前内容输出到客户端
50             sendMsg(user + ":" + result.getJson().getString("asynMsg"), from,
51                     to,type);
52         }
53 
54     }
55 
56     public void sendMsg(String content) {
57         sendMsg(content, "系统", null, "data");
58     }
59 
60     // / <summary>
61     // / 遍歷所有客戶端, 將消息傳送給客戶端
62     // / </summary>
63     // / <param name="orderType"></param>
64     public void sendMsg(String content, String from, String to, String type) {
65         synchronized (clients) {
66             clients.notifyAll();
67         }
68         JSONObject json = new JSONObject();
69         json.put(KEY, content);
70         json.put("from", from);
71         json.put("to", to);
72         json.put("type", type);
73         System.out.println(json);
74         if (to == null || to.toUpperCase().equals("ALL")) {
75             for (AsynResult value : clients.values()) {
76                 value.send(json);
77                 value.getContext().complete();
78             }
79             // 清空所有缓存
80             clients.clear();
81         } else {
82             AsynResult value = clients.get(to);
83             value.send(json);
84             System.out.println(value.getContext().getRequest().isAsyncStarted());
85             if(value.getContext().getRequest().isAsyncStarted()){
86             value.getContext().complete();
87             }
88         }
89     }
90 }

4. 通过jsp建立长链接

http://localhost:8080/Comet/CometServlet?content=&type=wait

5. 通过jsp响应长链接

http://localhost:8080/Comet/json/home!SendMsg.do

6. 通过java程式模拟http建立长链接

View Code
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.ResourceBundle;

import net.sf.json.JSONObject;

public class HttpCometUtils {
    // private static String host = "http://localhost:8080/Comet/";
    private static String action = "json/home!SendMsg.do?msgType=ALL";
    protected static ResourceBundle projectBundle = ResourceBundle
            .getBundle("DataBaseServer");
    public static Thread CometThread = null;
    private static String host = projectBundle.getString("web_server");
    public static boolean isLogin = false;
    static {
        if (!host.endsWith("/")) {
            host += "/";
        }
    }

    public HttpCometUtils() {
        // host = "http://localhost:8080/Comet/";
        if (!host.endsWith("/")) {
            host += "/";
        }
    }

    /**
     * @param urlString
     * @param method
     * @param type
     * @param msg
     * @throws IOException
     */
    public static void connectServer() {
        new Thread() {
            @Override
            public void run() {
                int errorCount = 0;
                while (isLogin) {
                    if (errorCount >= 10) {
                        try {
                            Thread.sleep(15000);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                            break;
                        }
                    }
                    URL url = null;
                    HttpURLConnection urlConnection = null;
                    try {
                        String serverURL = host
                                + "CometServlet?content=&type=wait&msgType=lott";
                        System.out.println(serverURL);
                        url = new URL(serverURL);

                        urlConnection = (HttpURLConnection) url
                                .openConnection();

                        urlConnection.setRequestMethod("GET");
                        urlConnection.setDoOutput(true);
                        urlConnection.setDoInput(true);
                        urlConnection.setUseCaches(false);
                        InputStream is = urlConnection.getInputStream();
                        byte[] b = new byte[is.available()];
                        is.read(b);
                        String jsmsg = new String(b, "utf-8");
                        System.out.println(jsmsg);
                        if(jsmsg.equals("")){
                            jsmsg = "{}";
                        }
                        JSONObject json = JSONObject.fromObject(jsmsg);
                        Object obj = null;
                        if (json.containsKey("type")) {
                            obj = json.get("type");
                            if (obj != null && "lott".equals(obj)) {
                                json = (JSONObject) json.get("msg");
                                if (json.containsKey("chatMsg")) {                                    
                                    System.out.println(json.get("chatMsg"));
                                }
                            }

                        }

                        errorCount = 0;
                    } catch (MalformedURLException e) {
                        errorCount++;
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (IOException e) {
                        errorCount++;
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (Exception e) {
                        errorCount++;
                        e.printStackTrace();
                    } finally {

                        if (urlConnection != null) {
                            urlConnection.disconnect();
                        }
                    }

                }
            }
        }.start();
    }

    public static void main(String[] args) {
        int x = new Random(System.currentTimeMillis()).nextInt(100);
        HttpCometUtils.isLogin = true;
        HttpCometUtils.connectServer();
    }
}

7. 通过java程式模拟http响应长链接

View Code
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Random;
import java.util.ResourceBundle;

public class HttpUtils {
    // private static String host = "http://localhost:8080/Comet/";
    private static String action = "json/home!SendMsg.do?msgType=ALL";
    protected static ResourceBundle projectBundle = ResourceBundle
            .getBundle("DataBaseServer");
    private static String host = "http://localhost:8080/Comet";//projectBundle.getString("web_server");
    static {
        if (!host.endsWith("/")) {
            host += "/";
        }
    }

    public HttpUtils() {
        if (!host.endsWith("/")) {
            host += "/";
        }
    }

    /**
     * @param urlString
     * @param method
     * @param type
     * @param msg
     * @throws IOException
     */
    public static void send(final String type, final String asynMsg) {
        new Thread() {
            @Override
            public void run() {


                URL url = null;
                HttpURLConnection urlConnection = null;
                try {
                    StringBuffer param = new StringBuffer();
                    param.append("&type=").append(type);
                    param.append("&asynMsg=").append(URLEncoder.encode(asynMsg, "UTF-8"));
                    String urlString = param.toString();
                    
                    String serverURL = host + action + urlString;
                    System.out.println(serverURL);
                    url = new URL(serverURL);
                    
                    urlConnection = (HttpURLConnection) url.openConnection();

                    urlConnection.setRequestMethod("GET");
                    // urlConnection.setDoOutput(true);
                    // urlConnection.setDoInput(true);
                    urlConnection.setUseCaches(false);

                    System.out.println(urlConnection.getResponseMessage());
                } catch (MalformedURLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (urlConnection != null) {
                        urlConnection.disconnect();
                    }
                }

            }

        }.start();
    }

    public static void main(String[] args) {
        int x = new Random(System.currentTimeMillis()).nextInt(100);
        HttpUtils.send("chat", "恭喜您中奖了.");
    }
}

 

posted @ 2012-11-22 09:05  秋日私语的博客  阅读(10097)  评论(0编辑  收藏  举报