2011-02-03 104 views
0

我想知道如何實現使用HTTP keepalive標頭的「推送」聊天服務器。我剛剛開始瞭解聊天服務器使用的兩種技術 - 長時間輪詢和推送 - 但我無法獲得關於幕後發生的事情的任何概念。如何使用HTTP Keepalive標頭實現聊天服務器

任何人都可以幫我嗎?任何客戶端/服務器端代碼將不勝感激!

回答

0

這裏是從Tomcat文檔一些彗星代碼(hhttp://tomcat.apache.org/tomcat-7.0-doc/aio.html)

public class ChatServlet 
extends HttpServlet implements CometProcessor { 

protected ArrayList<HttpServletResponse> connections = 
    new ArrayList<HttpServletResponse>(); 
protected MessageSender messageSender = null; 

public void init() throws ServletException { 
    messageSender = new MessageSender(); 
    Thread messageSenderThread = 
     new Thread(messageSender, "MessageSender[" + getServletContext().getContextPath() + "]"); 
    messageSenderThread.setDaemon(true); 
    messageSenderThread.start(); 
} 

public void destroy() { 
    connections.clear(); 
    messageSender.stop(); 
    messageSender = null; 
} 

/** 
* Process the given Comet event. 
* 
* @param event The Comet event that will be processed 
* @throws IOException 
* @throws ServletException 
*/ 
public void event(CometEvent event) 
    throws IOException, ServletException { 
    HttpServletRequest request = event.getHttpServletRequest(); 
    HttpServletResponse response = event.getHttpServletResponse(); 
    if (event.getEventType() == CometEvent.EventType.BEGIN) { 
     log("Begin for session: " + request.getSession(true).getId()); 
     PrintWriter writer = response.getWriter(); 
     writer.println("<!doctype html public \"-//w3c//dtd html 4.0 transitional//en\">"); 
     writer.println("<head><title>JSP Chat</title></head><body bgcolor=\"#FFFFFF\">"); 
     writer.flush(); 
     synchronized(connections) { 
      connections.add(response); 
     } 
    } else if (event.getEventType() == CometEvent.EventType.ERROR) { 
     log("Error for session: " + request.getSession(true).getId()); 
     synchronized(connections) { 
      connections.remove(response); 
     } 
     event.close(); 
    } else if (event.getEventType() == CometEvent.EventType.END) { 
     log("End for session: " + request.getSession(true).getId()); 
     synchronized(connections) { 
      connections.remove(response); 
     } 
     PrintWriter writer = response.getWriter(); 
     writer.println("</body></html>"); 
     event.close(); 
    } else if (event.getEventType() == CometEvent.EventType.READ) { 
     InputStream is = request.getInputStream(); 
     byte[] buf = new byte[512]; 
     do { 
      int n = is.read(buf); //can throw an IOException 
      if (n > 0) { 
       log("Read " + n + " bytes: " + new String(buf, 0, n) 
         + " for session: " + request.getSession(true).getId()); 
      } else if (n < 0) { 
       error(event, request, response); 
       return; 
      } 
     } while (is.available() > 0); 
    } 
} 

public class MessageSender implements Runnable { 

    protected boolean running = true; 
    protected ArrayList<String> messages = new ArrayList<String>(); 

    public MessageSender() { 
    } 

    public void stop() { 
     running = false; 
    } 

    /** 
    * Add message for sending. 
    */ 
    public void send(String user, String message) { 
     synchronized (messages) { 
      messages.add("[" + user + "]: " + message); 
      messages.notify(); 
     } 
    } 

    public void run() { 

     while (running) { 

      if (messages.size() == 0) { 
       try { 
        synchronized (messages) { 
         messages.wait(); 
        } 
       } catch (InterruptedException e) { 
        // Ignore 
       } 
      } 

      synchronized (connections) { 
       String[] pendingMessages = null; 
       synchronized (messages) { 
        pendingMessages = messages.toArray(new String[0]); 
        messages.clear(); 
       } 
       // Send any pending message on all the open connections 
       for (int i = 0; i < connections.size(); i++) { 
        try { 
         PrintWriter writer = connections.get(i).getWriter(); 
         for (int j = 0; j < pendingMessages.length; j++) { 
          writer.println(pendingMessages[j] + "<br>"); 
         } 
         writer.flush(); 
        } catch (IOException e) { 
         log("IOExeption sending message", e); 
        } 
       } 
      } 

     } 

    } 

} 

}

+0

謝謝Karthik!你能給我看一些客戶端代碼嗎? – SlowAndSteady 2011-02-03 05:58:12

0

有許多特定的技術,通常現在已知的名稱爲Comet。維基百科的文章鏈接了一個相當不錯的介紹。

另請參閱The Long Polling Technique

+0

由於拉夫。維基說,「長輪詢也被稱爲彗星編程」......我特別想知道「HTTP服務器推送」 - 我可以在我的程序中實現而不使用大量API。 – SlowAndSteady 2011-02-03 05:53:17