国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

網(wǎng)頁版在線聊天java Socket實(shí)現(xiàn)

2019-11-26 14:18:48
字體:
供稿:網(wǎng)友

本文為大家分享了一個(gè)滿足在線網(wǎng)頁交流需求的實(shí)例,由于java Socket實(shí)現(xiàn)的網(wǎng)頁版在線聊天功能,供大家參考,具體內(nèi)容如下

實(shí)現(xiàn)步驟:
1、使用awt組件和socket實(shí)現(xiàn)簡(jiǎn)單的單客戶端向服務(wù)端持續(xù)發(fā)送消息;
2、結(jié)合線程,實(shí)現(xiàn)多客戶端連接服務(wù)端發(fā)送消息;
3、實(shí)現(xiàn)服務(wù)端轉(zhuǎn)發(fā)客戶端消息至所有客戶端,同時(shí)在客戶端顯示;
4、把a(bǔ)wt組件生成的窗口界面改成前端jsp或者h(yuǎn)tml展示的界面,java socket實(shí)現(xiàn)的客戶端改為前端技術(shù)實(shí)現(xiàn)。

這里首先實(shí)現(xiàn)第一步的簡(jiǎn)單功能,難點(diǎn)在于:
1、沒有用過awt組件,沒有用過java相關(guān)的監(jiān)聽事件;
2、長(zhǎng)時(shí)間沒有使用socket進(jìn)行客戶端和服務(wù)端的交互,并且沒有真正進(jìn)行過cs結(jié)構(gòu)的開發(fā)。

實(shí)現(xiàn)功能的代碼
在線聊天客戶端:
1、生成圖形窗口界面輪廓
2、為輪廓添加關(guān)閉事件
3、在輪廓中加入輸入?yún)^(qū)域和內(nèi)容展示區(qū)域
4、為輸入?yún)^(qū)域添加回車事件
5、建立服務(wù)端連接并發(fā)送數(shù)據(jù)

package chat.chat;  import java.awt.BorderLayout; import java.awt.Frame; import java.awt.TextArea; import java.awt.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException;  /**  * 在線聊天客戶端 1、生成圖形窗口界面輪廓 2、為輪廓添加關(guān)閉事件 3、在輪廓中加入輸入?yún)^(qū)域和內(nèi)容展示區(qū)域 4、為輸入?yún)^(qū)域添加回車事件  * 5、建立服務(wù)端連接并發(fā)送數(shù)據(jù)  *  * @author tuzongxun123  *  */ public class ChatClient extends Frame {   // 用戶輸入?yún)^(qū)域   private TextField tfTxt = new TextField();   // 內(nèi)容展示區(qū)域   private TextArea tarea = new TextArea();   private Socket socket = null;   // 數(shù)據(jù)輸出流   private DataOutputStream dataOutputStream = null;    public static void main(String[] args) {     new ChatClient().launcFrame();   }    /**    * 建立一個(gè)簡(jiǎn)單的圖形化窗口    *    * @author:tuzongxun    * @Title: launcFrame    * @param    * @return void    * @date May 18, 2016 9:57:00 AM    * @throws    */   public void launcFrame() {     setLocation(300, 200);     this.setSize(200, 400);     add(tfTxt, BorderLayout.SOUTH);     add(tarea, BorderLayout.NORTH);     pack();     // 監(jiān)聽圖形界面窗口的關(guān)閉事件     this.addWindowListener(new WindowAdapter() {        @Override       public void windowClosing(WindowEvent e) {         System.exit(0);         disConnect();       }     });     tfTxt.addActionListener(new TFLister());     setVisible(true);     connect();   }    /**    * 連接服務(wù)器    *    * @author:tuzongxun    * @Title: connect    * @param    * @return void    * @date May 18, 2016 9:56:49 AM    * @throws    */   public void connect() {     try {       // 新建服務(wù)端連接       socket = new Socket("127.0.0.1", 8888);       // 獲取客戶端輸出流       dataOutputStream = new DataOutputStream(socket.getOutputStream());       System.out.println("連上服務(wù)端");     } catch (UnknownHostException e) {       e.printStackTrace();     } catch (IOException e) {       e.printStackTrace();     }   }    /**    * 關(guān)閉客戶端資源    *    * @author:tuzongxun    * @Title: disConnect    * @param    * @return void    * @date May 18, 2016 9:57:46 AM    * @throws    */   public void disConnect() {     try {       dataOutputStream.close();       socket.close();     } catch (IOException e) {       e.printStackTrace();     }   }    /**    * 向服務(wù)端發(fā)送消息    *    * @author:tuzongxun    * @Title: sendMessage    * @param @param text    * @return void    * @date May 18, 2016 9:57:56 AM    * @throws    */   private void sendMessage(String text) {     try {       dataOutputStream.writeUTF(text);       dataOutputStream.flush();     } catch (IOException e1) {       e1.printStackTrace();     }   }    /**    * 圖形窗口輸入?yún)^(qū)域監(jiān)聽回車事件    *    * @author tuzongxun123    *    */   private class TFLister implements ActionListener {      @Override     public void actionPerformed(ActionEvent e) {       String text = tfTxt.getText().trim();       tarea.setText(text);       tfTxt.setText("");       // 回車后發(fā)送數(shù)據(jù)到服務(wù)器       sendMessage(text);     }   } } 

服務(wù)端:

package chat.chat;  import java.io.DataInputStream; import java.io.EOFException; import java.io.IOException; import java.net.BindException; import java.net.ServerSocket; import java.net.Socket;  /**  * java使用socket和awt組件簡(jiǎn)單實(shí)現(xiàn)在線聊天功能服務(wù)端 可以實(shí)現(xiàn)一個(gè)客戶端連接后不斷向服務(wù)端發(fā)送消息  * 但不支持多個(gè)客戶端同時(shí)連接,原因在于代碼中獲得客戶端連接后會(huì)一直循環(huán)監(jiān)聽客戶端輸入,造成阻塞  * 以至于服務(wù)端無法二次監(jiān)聽另外的客戶端,如要實(shí)現(xiàn),需要使用異步或者多線程  *  * @author tuzongxun123  *  */ public class ChatServer {    public static void main(String[] args) {     // 是否成功啟動(dòng)服務(wù)端     boolean isStart = false;     // 服務(wù)端socket     ServerSocket ss = null;     // 客戶端socket     Socket socket = null;     // 服務(wù)端讀取客戶端數(shù)據(jù)輸入流     DataInputStream dataInputStream = null;     try {       // 啟動(dòng)服務(wù)器       ss = new ServerSocket(8888);     } catch (BindException e) {       System.out.println("端口已在使用中");       // 關(guān)閉程序       System.exit(0);     } catch (Exception e) {       e.printStackTrace();     }      try {       isStart = true;       while (isStart) {         boolean isConnect = false;         // 啟動(dòng)監(jiān)聽         socket = ss.accept();         System.out.println("one client connect");         isConnect = true;         while (isConnect) {           // 獲取客戶端輸入流           dataInputStream = new DataInputStream(               socket.getInputStream());           // 讀取客戶端傳遞的數(shù)據(jù)           String message = dataInputStream.readUTF();           System.out.println("客戶端說:" + message);         }        }     } catch (EOFException e) {       System.out.println("client closed!");     } catch (Exception e) {       e.printStackTrace();     } finally {       // 關(guān)閉相關(guān)資源       try {         dataInputStream.close();         socket.close();       } catch (IOException e) {         e.printStackTrace();       }     }   } } 

繼續(xù),在單客戶端連接的基礎(chǔ)上,這里第二步需要實(shí)現(xiàn)多客戶端的連接,也就需要使用到線程。每當(dāng)有一個(gè)新的客戶端連接上來,服務(wù)端便需要新啟動(dòng)一個(gè)線程進(jìn)行處理,從而解決之前的循環(huán)讀取中造成阻塞的問題。

寫線程通常有兩種方法,集成Thread或者實(shí)現(xiàn)runnable接口,原則上是能實(shí)現(xiàn)runnable的情況下就不繼承,因?yàn)閷?shí)現(xiàn)接口的方式更加靈活。

客戶端代碼相較之前沒有變化,變得是服務(wù)端,因此這里便只貼出服務(wù)端代碼:

java使用socket和awt組件以及多線程簡(jiǎn)單實(shí)現(xiàn)在線聊天功能服務(wù)端 :

實(shí)現(xiàn)多個(gè)客戶端連接后不斷向服務(wù)端發(fā)送消息, 相對(duì)于第一個(gè)版本,重點(diǎn)在于使用了多線程。服務(wù)端還未實(shí)現(xiàn)轉(zhuǎn)發(fā)功能,客戶端圖形窗口中只能看到自己輸入的信息,不能看到其他客戶端發(fā)送的消息。

package chat.chat;  import java.io.DataInputStream; import java.io.EOFException; import java.io.IOException; import java.net.BindException; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException;  /**  * *  * @author tuzongxun123  *  */ public class ChatServer {    public static void main(String[] args) {     new ChatServer().start();   }    // 是否成功啟動(dòng)服務(wù)端   private boolean isStart = false;   // 服務(wù)端socket   private ServerSocket ss = null;   // 客戶端socket   private Socket socket = null;    public void start() {     try {       // 啟動(dòng)服務(wù)器       ss = new ServerSocket(8888);     } catch (BindException e) {       System.out.println("端口已在使用中");       // 關(guān)閉程序       System.exit(0);     } catch (Exception e) {       e.printStackTrace();     }      try {       isStart = true;       while (isStart) {         // 啟動(dòng)監(jiān)聽         socket = ss.accept();         System.out.println("one client connect");         // 啟動(dòng)客戶端線程         Client client = new Client(socket);         new Thread(client).start();       }     } catch (Exception e) {       e.printStackTrace();     } finally {       // 關(guān)閉服務(wù)       try {         ss.close();       } catch (IOException e) {         e.printStackTrace();       }     }    }    /**    * 客戶端線程    *    * @author tuzongxun123    *    */   class Client implements Runnable {     // 客戶端socket     private Socket socket = null;     // 客戶端輸入流     private DataInputStream dataInputStream = null;     private boolean isConnect = false;      public Client(Socket socket) {       this.socket = socket;       try {         isConnect = true;         // 獲取客戶端輸入流         dataInputStream = new DataInputStream(socket.getInputStream());       } catch (IOException e) {         e.printStackTrace();       }     }      @Override     public void run() {       isConnect = true;       try {         while (isConnect) {           // 讀取客戶端傳遞的數(shù)據(jù)           String message = dataInputStream.readUTF();           System.out.println("客戶端說:" + message);         }       } catch (EOFException e) {         System.out.println("client closed!");       } catch (SocketException e) {         System.out.println("Client is Closed!!!!");       } catch (Exception e) {         e.printStackTrace();       } finally {         // 關(guān)閉相關(guān)資源         try {           dataInputStream.close();           socket.close();         } catch (IOException e) {           e.printStackTrace();         }       }     }    }  } 

上面主要介紹了利用線程使服務(wù)端實(shí)現(xiàn)了能夠接收多客戶端請(qǐng)求的功能,這里便需要客戶端接收多客戶端消息的同時(shí)還能把消息轉(zhuǎn)發(fā)到每個(gè)連接的客戶端,并且客戶端要能在內(nèi)容顯示區(qū)域顯示出來,從而實(shí)現(xiàn)簡(jiǎn)單的在線群聊。

在實(shí)現(xiàn)客戶端轉(zhuǎn)發(fā),無非就是增加輸出流;而之前客戶端都只發(fā)不收,這里也需要更改客戶端達(dá)到循環(huán)接收服務(wù)端消息的目的,因此也需要實(shí)現(xiàn)多線程。

在實(shí)現(xiàn)這個(gè)功能的時(shí)候,偶然想起隨機(jī)生成驗(yàn)證碼的功能,于是也靈機(jī)一動(dòng)隨機(jī)給每個(gè)客戶端生成一個(gè)名字,從而在輸出的時(shí)候看起來更加像是群聊,不僅有消息輸出,還能看到是誰。

實(shí)現(xiàn)這些功能之后,基本上就可以幾個(gè)人同時(shí)在線群聊了,因?yàn)榇a中有main方法,因此可以把服務(wù)端和客戶端都打成可執(zhí)行jar包,可參考我的另一篇博文:使用eclipse創(chuàng)建java程序可執(zhí)行jar包

之后在桌面雙擊相應(yīng)的jar文件啟動(dòng)服務(wù)端和客戶端即可,不需要再依賴eclipse運(yùn)行。

修改后的客戶端代碼如下:

package chat.chat;  import java.awt.BorderLayout; import java.awt.Frame; import java.awt.TextArea; import java.awt.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException; import java.util.Random;  /**  * 在線聊天客戶端 步驟:  *1、生成圖形窗口界面輪廓  *2、為輪廓添加關(guān)閉事件  *3、在輪廓中加入輸入?yún)^(qū)域和內(nèi)容展示區(qū)域  *4、為輸入?yún)^(qū)域添加回車事件  * 5、建立服務(wù)端連接并發(fā)送數(shù)據(jù)  *  * @author tuzongxun123  *  */ public class ChatClient extends Frame {   /**    *    */   private static final long serialVersionUID = 1L;   // 用戶輸入?yún)^(qū)域   private TextField tfTxt = new TextField();   // 內(nèi)容展示區(qū)域   private TextArea tarea = new TextArea();   private Socket socket = null;   // 數(shù)據(jù)輸出流   private DataOutputStream dataOutputStream = null;   // 數(shù)據(jù)輸入流   private DataInputStream dataInputStream = null;   private boolean isConnect = false;   Thread tReceive = new Thread(new ReceiveThread());   String name = "";    public static void main(String[] args) {     ChatClient chatClient = new ChatClient();     chatClient.createName();     chatClient.launcFrame();    }    /**    * 建立一個(gè)簡(jiǎn)單的圖形化窗口    *    * @author:tuzongxun    * @Title: launcFrame    * @param    * @return void    * @date May 18, 2016 9:57:00 AM    * @throws    */   public void launcFrame() {     setLocation(300, 200);     this.setSize(200, 400);     add(tfTxt, BorderLayout.SOUTH);     add(tarea, BorderLayout.NORTH);     // 根據(jù)窗口里面的布局及組件的preferedSize來確定frame的最佳大小     pack();     // 監(jiān)聽圖形界面窗口的關(guān)閉事件     this.addWindowListener(new WindowAdapter() {        @Override       public void windowClosing(WindowEvent e) {         System.exit(0);         disConnect();       }     });     tfTxt.addActionListener(new TFLister());     // 設(shè)置窗口可見     setVisible(true);     connect();     // 啟動(dòng)接受消息的線程     tReceive.start();   }    /**    * 連接服務(wù)器    *    * @author:tuzongxun    * @Title: connect    * @param    * @return void    * @date May 18, 2016 9:56:49 AM    * @throws    */   public void connect() {     try {       // 新建服務(wù)端連接       socket = new Socket("127.0.0.1", 8888);       // 獲取客戶端輸出流       dataOutputStream = new DataOutputStream(socket.getOutputStream());       dataInputStream = new DataInputStream(socket.getInputStream());       System.out.println("連上服務(wù)端");       isConnect = true;     } catch (UnknownHostException e) {       e.printStackTrace();     } catch (IOException e) {       e.printStackTrace();     }   }    // 生成隨機(jī)的客戶端名字   public void createName() {     String[] str1 = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",         "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",         "w", "x", "y", "z", "1", "2", "3", "4", "5", "6", "7", "8",         "9", "0", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",         "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",         "W", "X", "Y", "Z" };     Random ran = new Random();      for (int i = 0; i < 6; i++) {       // long num = Math.round(Math.random() * (str1.length - 0) + 0);       // int n = (int) num;       int n = ran.nextInt(str1.length);       if (n < str1.length) {         String str = str1[n];         name = name + str;         System.out.println(name);       } else {         i--;         continue;       }      }     this.setTitle(name);   }    /**    * 關(guān)閉客戶端資源    *    * @author:tuzongxun    * @Title: disConnect    * @param    * @return void    * @date May 18, 2016 9:57:46 AM    * @throws    */   public void disConnect() {     try {       isConnect = false;       // 停止線程       tReceive.join();     } catch (InterruptedException e) {       e.printStackTrace();     } finally {       try {         if (dataOutputStream != null) {           dataOutputStream.close();         }         if (socket != null) {           socket.close();           socket = null;         }        } catch (IOException e) {         e.printStackTrace();       }     }   }    /**    * 向服務(wù)端發(fā)送消息    *    * @author:tuzongxun    * @Title: sendMessage    * @param @param text    * @return void    * @date May 18, 2016 9:57:56 AM    * @throws    */   private void sendMessage(String text) {     try {       dataOutputStream.writeUTF(name + ":" + text);       dataOutputStream.flush();     } catch (IOException e1) {       e1.printStackTrace();     }   }    /**    * 圖形窗口輸入?yún)^(qū)域監(jiān)聽回車事件    *    * @author tuzongxun123    *    */   private class TFLister implements ActionListener {      @Override     public void actionPerformed(ActionEvent e) {       String text = tfTxt.getText().trim();       // 清空輸入?yún)^(qū)域信息       tfTxt.setText("");       // 回車后發(fā)送數(shù)據(jù)到服務(wù)器       sendMessage(text);     }    }    private class ReceiveThread implements Runnable {      @Override     public void run() {       try {         while (isConnect) {           String message = dataInputStream.readUTF();           System.out.println(message);           String txt = tarea.getText();           if (txt != null && !"".equals(txt.trim())) {             message = tarea.getText() + "/n" + message;           }           tarea.setText(message);         }       } catch (IOException e) {         e.printStackTrace();       }     }    } } 

修改后的服務(wù)端代碼如下:

package chat.chat;  import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.EOFException; import java.io.IOException; import java.net.BindException; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.util.ArrayList; import java.util.List;  /**  * java使用socket和awt組件以及多線程簡(jiǎn)單實(shí)現(xiàn)在線聊天功能服務(wù)端 :  * 實(shí)現(xiàn)服務(wù)端把接收到的客戶端信息轉(zhuǎn)發(fā)到所有連接的客戶端,并且讓客戶端讀取到這些信息并顯示在內(nèi)容顯示區(qū)域中。  *  * @author tuzongxun123  *  */ public class ChatServer {    public static void main(String[] args) {     new ChatServer().start();   }    // 是否成功啟動(dòng)服務(wù)端   private boolean isStart = false;   // 服務(wù)端socket   private ServerSocket ss = null;   // 客戶端socket   private Socket socket = null;   // 保存客戶端集合   List<Client> clients = new ArrayList<Client>();    public void start() {     try {       // 啟動(dòng)服務(wù)器       ss = new ServerSocket(8888);     } catch (BindException e) {       System.out.println("端口已在使用中");       // 關(guān)閉程序       System.exit(0);     } catch (Exception e) {       e.printStackTrace();     }      try {       isStart = true;       while (isStart) {         // 啟動(dòng)監(jiān)聽         socket = ss.accept();         System.out.println("one client connect");         // 啟動(dòng)客戶端線程         Client client = new Client(socket);          new Thread(client).start();         clients.add(client);       }     } catch (Exception e) {       e.printStackTrace();     } finally {       // 關(guān)閉服務(wù)       try {         ss.close();       } catch (IOException e) {         e.printStackTrace();       }     }    }    /**    * 客戶端線程    *    * @author tuzongxun123    *    */   private class Client implements Runnable {     // 客戶端socket     private Socket socket = null;     // 客戶端輸入流     private DataInputStream dataInputStream = null;     // 客戶端輸出流     private DataOutputStream dataOutputStream = null;     private boolean isConnect = false;      public Client(Socket socket) {       this.socket = socket;       try {         isConnect = true;         // 獲取客戶端輸入流         dataInputStream = new DataInputStream(socket.getInputStream());         // 獲取客戶端輸出流         dataOutputStream = new DataOutputStream(             socket.getOutputStream());       } catch (IOException e) {         e.printStackTrace();       }     }      /**      * 向客戶端群發(fā)(轉(zhuǎn)發(fā))數(shù)據(jù)      *      * @author:tuzongxun      * @Title: sendMessageToClients      * @param @param message      * @return void      * @date May 18, 2016 11:28:10 AM      * @throws      */     public void sendMessageToClients(String message) {       try {         dataOutputStream.writeUTF(message);       } catch (SocketException e) {        } catch (IOException e) {         e.printStackTrace();       }     }      @Override     public void run() {       isConnect = true;       Client c = null;       try {         while (isConnect) {           // 讀取客戶端傳遞的數(shù)據(jù)           String message = dataInputStream.readUTF();           System.out.println("客戶端說:" + message);           for (int i = 0; i < clients.size(); i++) {             c = clients.get(i);              c.sendMessageToClients(message);           }          }       } catch (EOFException e) {         System.out.println("client closed!");       } catch (SocketException e) {         if (c != null) {           clients.remove(c);         }         System.out.println("Client is Closed!!!!");       } catch (Exception e) {         e.printStackTrace();       } finally {         // 關(guān)閉相關(guān)資源         try {           if (dataInputStream != null) {             dataInputStream.close();           }           if (socket != null) {             socket.close();             socket = null;           }         } catch (IOException e) {           e.printStackTrace();         }       }     }   }  } 

就先為大家介紹到這里,之后如果有新的內(nèi)容再為大家進(jìn)行更新。

關(guān)于網(wǎng)頁在線聊天功能的實(shí)現(xiàn)大,大家還可以參考一下幾篇文章進(jìn)行學(xué)習(xí):

java實(shí)現(xiàn)一個(gè)簡(jiǎn)單TCPSocket聊天室功能分享

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家可以繼續(xù)關(guān)注武林網(wǎng)的更多精彩內(nèi)容。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 和静县| 辉县市| 太仓市| 海兴县| 禹城市| 灯塔市| 建平县| 大名县| 牙克石市| 远安县| 富顺县| 平和县| 双牌县| 和硕县| 威海市| 淮南市| 通化市| 历史| 遵义县| 奉新县| 门头沟区| 聂拉木县| 荥阳市| 尚志市| 丰顺县| 凤山市| 六安市| 太白县| 昔阳县| 绍兴县| 固镇县| 河津市| 宽甸| 宜州市| 洛阳市| 孟连| 惠水县| 崇礼县| 宣城市| 邵阳市| 罗甸县|