1、功能介紹java
該功能實現了一個相似QQ的最簡單多人聊天室,以下圖所示。app
2、目錄結構socket
3、服務端this
1)SocketServer類,該類是服務端的主類,主要負責建立聊天窗口,建立監聽客戶端的線程:spa
package multiThreadChatSocketServer; import java.awt.*; 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.ServerSocket; import java.net.Socket; public class SocketServer { private TextArea ta; private TextField tf; private ServerSocket ss; private Socket s; private DataInputStream dis; private DataOutputStream dos; public TextField getTextField() { return tf; } public TextArea getTextArea() { return ta; } public DataInputStream getDataInputStream() { return dis; } public DataOutputStream getDataOutputStream() { return dos; } public static void main(String[] args) { SocketServer socketServer = new SocketServer(); socketServer.createUI(); socketServer.connect(); socketServer.createThread(); } public void close() { try { dis.close(); dos.close(); s.close(); ss.close(); } catch (IOException e) { e.printStackTrace(); } } /** * 建立界面 */ private void createUI(){ Frame f=new Frame("socketServer"); ta = new TextArea(); tf = new TextField(); Button send = new Button("send"); Panel p = new Panel(); p.setLayout(new BorderLayout()); p.add(tf, "Center"); p.add(send, "East"); f.add(ta, "Center"); f.add(p, "South"); MyServerListener listener = new MyServerListener(this); //無論點擊發送按鈕仍是輸入框回車,都會觸發listener事件 send.addActionListener(listener); tf.addActionListener(listener); //當關閉窗口的時候,退出系統 f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); f.setSize(400,400); f.setVisible(true); } /** * 建立鏈接 */ public void connect(){ try { ss=new ServerSocket(8888); s=ss.accept(); dis=new DataInputStream(s.getInputStream()); dos=new DataOutputStream(s.getOutputStream()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 啓動監聽客戶端發來的消息的線程 */ public void createThread() { MyServerReader reader = new MyServerReader(this); reader.start(); } }
2)MyServerReader類,該類實時監聽客戶端輸入的信息,若是對方輸入「bye」,則退出監聽並關閉窗口.net
package multiThreadChatSocketServer; import java.awt.TextArea; import java.io.DataInputStream; import java.io.IOException; /** * 監聽客戶端發過來的消息,關顯示在服務端的界面上 * @author Administrator * */ class MyServerReader extends Thread { private SocketServer server; public MyServerReader(SocketServer server) { this.server = server; } public void run() { String info; DataInputStream dis = server.getDataInputStream(); TextArea ta = server.getTextArea(); try { while (true) { info = dis.readUTF(); ta.append("對方說: " + info + "\n"); if (info.equals("bye")) { server.close(); System.exit(0); } } } catch (IOException e) { e.printStackTrace(); } } }
3)MyServerListener類,是點發送按鈕的時候執行的類線程
package multiThreadChatSocketServer; import java.awt.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; /** * 當點擊發服務端的送按鈕的時候,將信息顯示在服務端的界面上,並將信息發送給客戶端 * @author Administrator * */ class MyServerListener implements ActionListener { private SocketServer server; public MyServerListener(SocketServer server) { this.server = server; } public void actionPerformed(ActionEvent e) { TextField tf = server.getTextField(); String info = tf.getText(); server.getTextArea().append("本身說: " + info + "\n"); try { // writeUTF(value:String) :將 UTF-8 字符串寫入字節流。先寫入以字節表示的 UTF-8 字符串長度(做爲 16 位整數),而後寫入表示字符串字符的字節。 // 由於先把字符長度寫入二進制,16位能保存的字節長度爲65535,超出這個長度會報RangeError。 // writeUTFBytes(value:String):不添加字節長度直接寫入字符串的字節數據。所以在讀取的時候須要指定字節長度 server.getDataOutputStream().writeUTF(info); } catch (IOException e1) { e1.printStackTrace(); } if (info.equals("bye")) { server.close(); System.exit(0); } tf.setText(""); tf.requestFocus(); } }
4、客戶端code
1)SocketClient類orm
package multiThreadChatSocketClient; import java.awt.*; 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.ServerSocket; import java.net.Socket; public class SocketClient { private TextArea ta; private TextField tf; private Socket s; private DataInputStream dis; private DataOutputStream dos; public TextField getTextField() { return tf; } public TextArea getTextArea() { return ta; } public DataInputStream getDataInputStream() { return dis; } public DataOutputStream getDataOutputStream() { return dos; } public static void main(String[] args) { SocketClient socketClient = new SocketClient(); socketClient.createUI(); socketClient.connect(); socketClient.createThread(); } public void close() { try { dis.close(); dos.close(); s.close(); } catch (IOException e) { e.printStackTrace(); } } /** * 建立界面 */ private void createUI(){ Frame f=new Frame("socketClient"); ta = new TextArea(); tf = new TextField(); Button send = new Button("send"); Panel p = new Panel(); p.setLayout(new BorderLayout()); p.add(tf, "Center"); p.add(send, "East"); f.add(ta, "Center"); f.add(p, "South"); MyClientListener listener = new MyClientListener(this); //無論點擊發送按鈕仍是輸入框回車,都會觸發listener事件 send.addActionListener(listener); tf.addActionListener(listener); //當關閉窗口的時候,退出系統 f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); f.setSize(400,400); f.setVisible(true); } /** * 建立鏈接 */ public void connect(){ try { s = new Socket("127.0.0.1", 8888); dis=new DataInputStream(s.getInputStream()); dos=new DataOutputStream(s.getOutputStream()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 啓動監聽服務端發來的消息的線程 */ public void createThread() { MyClientReader reader = new MyClientReader(this); reader.start(); } }
2)MyClientReader類server
package multiThreadChatSocketClient; import java.awt.TextArea; import java.io.DataInputStream; import java.io.IOException; /** * 監聽服務端發過來的消息,關顯示在客戶端的界面上 * @author Administrator * */ class MyClientReader extends Thread { private SocketClient client; public MyClientReader(SocketClient client) { this.client = client; } public void run() { String info; DataInputStream dis = client.getDataInputStream(); TextArea ta = client.getTextArea(); try { while (true) { info = dis.readUTF(); ta.append("對方說: " + info + "\n"); if (info.equals("bye")) { client.close(); System.exit(0); } } } catch (IOException e) { e.printStackTrace(); } } }
3)MyClientListener類
package multiThreadChatSocketClient; import java.awt.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; /** * 當點擊客戶端的發送按鈕的時候,將信息顯示在客戶端的界面上,並將信息發送給服務端 * @author Administrator * */ class MyClientListener implements ActionListener { private SocketClient client; public MyClientListener(SocketClient client) { this.client = client; } public void actionPerformed(ActionEvent e) { TextField tf = client.getTextField(); String info = tf.getText(); client.getTextArea().append("本身說: " + info + "\n"); try { client.getDataOutputStream().writeUTF(info); } catch (IOException e1) { e1.printStackTrace(); } if (info.equals("bye")) { client.close(); System.exit(0); } tf.setText(""); tf.requestFocus(); } }