以下引用自初燃之炎.伏翼之風的Blog 用WEB端做SOCKET服務器(如Resin) |
很久沒上來留言了,這一陣子平時也是偶爾想起這里,這次心血來潮想留點什么,也希望高手提供一些更先進的編程思想。這次就談SOCKET,這里這方面的介紹還是比較多的,大多都是C/S結構的為服務端,但是結合其它的應用上就差些,必須單獨啟動服務,如果擴展到B/S結構就有很多優勢(其實也是個人感覺)......
我就把一些簡單結構提出來,供大家參考和指教: 結構:
Message.java 消息類,用來組裝通訊消息
MessageServlet.java 用servlet調用下類,為了和Resin等同時啟動 MessageServer.java 啟動封裝類,指定監聽端口 ServerListener.java 服務端管理類,起分發、處理等用途 ClientListener.java 每個客戶端的監聽線程 MessageListener.java 每條消息的線程,處理完則關閉
至于Message.java,我就不把我的文件全拷來,用個最簡單的代替吧,大家也可以提供自己的想法,我自己的那個針對性太強,適用性太低,就參考下類吧(字符串處理比較直觀,用byte比較穩定):
package net.fool; import java.io.Serializable; public class Message implements Serializable{ //信息類型 //private MessageType type = MessageType.HALFBAKED; //大家各抒己見吧 //信息內容 private String content = ""; //構造函數 public Message(String mess){ this.content = mess; } public String toString(){ return this.content; } }
至于MessageServlet.java
只是一個在init方法里啟動服務,在destroy中關閉服務而已 比如對resin來說只要在某一個配置應用的web.xml添加 <servlet> <servlet-name>mss</servlet-name> <servlet-class>net.fool.MessageServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> 這一段文字,就可以在resin啟動時啟動該socket服務了 package net.fool; import javax.servlet.*; import javax.servlet.http.*; public class MessageServlet extends HttpServlet{ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, java.io.IOException{ } public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, java.io.IOException{ } /** * <p>初始化servlet. * * @param cfg Servlet configuration information */ public void init(ServletConfig cfg) throws ServletException{ super.init(cfg); MessageServer mb = MessageServer.Connect(5678); } /** * <p>清除servlet. */ public void destroy(){ super.destroy(); MessageServer.DisConnect(); } } 至于MessageServer.java, 則是創建一個ServerSocket,并啟動監聽線程,然后客戶端連接上就可以做后面的事情了 package net.fool; import java.util.*; import java.io.*; import java.net.*; import java.nio.*; public class MessageServer{ private static int messagePort = 5678; private static MessageServer mess; private static ServerSocket server; private static ServerListener serverListener; private MessageServer(){ try{ server = new ServerSocket(messagePort); System.out.println("MessageServer listening to *:"+String.valueOf(messagePort)+""); serverListener = new ServerListener(server); serverListener.start(); }catch(Exception e){ e.printStackTrace(); } } public synchronized static MessageServer Connect(int port){ MessageServer.messagePort = port; if (mess == null) { mess = new MessageServer(); }else if(server.getLocalPort()!=port){ DisConnect(); mess = new MessageServer(); } return mess; } public synchronized static MessageServer Connect(){ return Connect(messagePort); } public synchronized static void DisConnect(){ try{ mess = null; System.out.println("close MessageServer for port:"+String.valueOf(server.getLocalPort())+""); serverListener = null; server.close(); }catch(Exception e){} } } ServerListener.java, 則是一個監聽線程,也是一個主服務線程 package net.fool; import java.util.*; import java.io.*; import java.net.*; public class ServerListener extends Thread{ private ServerSocket serverSocket; private static Hashtable clients = new Hashtable(); //對應每個客戶端的登陸信息 private static Hashtable messages = new Hashtable(); //未處理消息集合 private static Socket clientSocket; //多客戶端 public ServerListener(ServerSocket serverSocket) throws Exception{ super("ServerListener"); this.serverSocket=serverSocket; } public void run(){ try{ while(true){ clientSocket=serverSocket.accept(); Response(clientSocket); }//while }catch(Exception e){System.out.println(e);} }//run public static void Response(Socket client) throws Exception{ try{ ClientListener clistener = new ClientListener(client,clients); clistener.start(); }catch(Exception e){ System.out.println("連接到" +client.getInetAddress().getHostAddress()+"失敗!"); } } //添加消息,可從B/S結構中傳入需發布的消息 public static boolean addMessage(Message mess) throws Exception{ boolean flag = false; synchronized(messages){ try{ messages.put(mess,"newMessage"); //待擴充 MessageListener mlistener = new MessageListener(mess,messages); mlistener.start(); }catch(Exception e){ System.out.println("發布消息" +mess.toString()+"失敗!"); return flag; } } flag = true; return flag; } //根據消息類型處理消息 消息分發 //這里只是發送到所有客戶端 public synchronized static boolean releaseMessage(Message mess) throws Exception{ Enumeration enumeration = clients.keys(); for(;enumeration.hasMoreElements();){ try{ Socket soc = (Socket)enumeration.nextElement(); DataOutputStream dos = new DataOutputStream(soc.getOutputStream()); dos.write(mess.toString().getBytes("GBK")); }catch(Exception e){} } return true; } }//class ClientListener.java, 則是每一個客戶端監聽線程,得到客戶端發送的消息,整理起來,把相關消息丟給主服務分發消息 package net.fool; import java.util.*; import java.io.*; import java.net.*; public class ClientListener extends Thread{ private static Hashtable clients; private Message userMessage; private Socket socket; private BufferedReader reader; private boolean listening = true; public ClientListener(Socket socket,Hashtable clients) throws Exception{ super("ClientListener"); this.clients=clients; this.socket=socket; this.reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); } public void run(){ try { listener(); }catch(Exception e) { e.printStackTrace(); }finally{ synchronized(clients){ //String ss_c = ("斷開連接:"+socket); clients.remove(socket); try{ socket.close(); reader.close(); //ServerListener.releaseMessage(某人下線消息); }catch(Exception ex){} //System.out.println(ss_c); } } } private void listener() throws Exception{ synchronized(clients){ clients.put(socket,userMessage); } //擴展后應放在下面的循環內,當為某人的上線消息時才執行這個 while(listening) { //讀取客戶端發送來的消息 String rLine = reader.readLine(); if(rLine==null||rLine.equals("\r\n")) break;; Message me = new Message(rLine); //當為某人的上線消息時 synchronized...... ServerListener.addMessage(me); } } }//class MessageListener.java, 則是每一條消息監聽線程,只是讓消息堆積起來慢慢處理 package net.fool; import java.util.*; import java.io.*; import java.net.*; public class MessageListener extends Thread{ private static Hashtable messages; private Message message; private boolean listening = true; public MessageListener(Message message,Hashtable messages) throws Exception{ super("MessageListener"); this.messages=messages; this.message=message; } public void run(){ try { listener(); }catch(Exception e) { e.printStackTrace(); }finally{ synchronized(messages){ messages.remove(message); try{ message = null; }catch(Exception ex){} } } } private void listener() throws Exception{ while(listening){ //本條消息的處理 //包括即時和等待,存儲和丟失,個人和群發等等判斷,待擴充Message類 try{ listening = !ServerListener.releaseMessage(message); }catch(Exception e){e.printStackTrace();} } } }//class |
只有注冊用戶登錄后才能發表評論。 | ||
![]() |
||
網站導航:
博客園
IT新聞
Chat2DB
C++博客
博問
管理
|
||
相關文章:
|
||