java socket之多人聊天室Demo

一、功能介绍

该功能实现了一个类似QQ的最简单多人聊天室,如下图所示。

java socket之多人聊天室Demo

二、目录结构

java socket之多人聊天室Demo

三、服务端

1)SocketServer类,该类是服务端的主类,主要负责创建聊天窗口,创建监听客户端的线程:

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”,则退出监听并关闭窗口

 

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();
     }
 }

四、客户端

1)SocketClient类

 

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类

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();
     }
 }