以下引用自初燃之炎.伏翼之風的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
          posted on 2006-05-23 06:40 大狗刀刀 閱讀(296) 評論(0)  編輯  收藏 所屬分類: JSP學習心得
           
          主站蜘蛛池模板: 合山市| 永安市| 杭州市| 健康| 阿克陶县| 阿尔山市| 香河县| 包头市| 济南市| 九台市| 易门县| 东明县| 南阳市| 万宁市| 呼图壁县| 句容市| 庆云县| 萨迦县| 六安市| 嘉善县| 德昌县| 浪卡子县| 肃宁县| 威宁| 余江县| 吉林市| 密云县| 报价| 海丰县| 靖远县| 南丹县| 富阳市| 榆中县| 南部县| 西平县| 文安县| 霞浦县| 简阳市| 平安县| 蒙阴县| 江川县|