Java实战项目(四)——聊天室

一.项目目标

实现基于C/S模式的聊天室程序。
聊天室共分为服务器端和客户端两部分。

  1. 服务器端功能
    (1)提供多线程的聊天服务处理。
    (2)在服务器端屏幕上提示客户端进入,显示客户端聊天内容。
    (3)当某客户端输入字符“quit”时断开该客户端的连接。
  2. 客户端功能
    (1)可以配置要连接服务器的IP地址和端口号。
    (2)配置用户昵称后连接。
    (3)可以向所有人发送消息。
    (4)显示本聊天室中的该用户登录后的所有信息。
    (5)显示在该用户登录之后登录的用户登录信息。

二.项目分析

  1. 界面
    服务器端界面只有一个文本区域,显示用户登录信息及全部在线用户发送的消息,如下图所示
    Java实战项目(四)——聊天室_第1张图片

客户端界面包括如下部分:
(1)服务器IP设置。
(2)服务器端口设置。
(3)用户名设置。
(4)聊天记录显示。
(5)与服务器连接按钮。
(6)消息发送。
界面如下图所示
Java实战项目(四)——聊天室_第2张图片

三.代码实现

CServer.java:

package Chat;

import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Enumeration;
import java.util.Hashtable;



public class CServer extends Frame{
    TextArea textArea = new TextArea(20, 50);  //显示用户登录信息及全部在线用户所发送的信息
    Socket socket = null;
    Socket socket1 = null;
    Hashtable hashtable = new Hashtable();
    //客户端不传参数时服务器窗口标题为空
    public CServer() throws HeadlessException {
        super();
        init();
    }

    //客户端传入参数作为服务器窗口标题
    public CServer(String string) throws HeadlessException {
        super(string);
        init();
    }

    //向所有在服务器中的客户端进行广播
    public void boradCast(String str, Socket self) {
        // TODO Auto-generated method stub
        Enumeration enumeration = hashtable.keys();
        System.out.println("本聊天室共有"+hashtable.size()+"人");
        PrintStream printStream = null;
        textArea.append(str);
        while (enumeration.hasMoreElements()) {
            String s = (String)enumeration.nextElement();
            socket1 = (Socket)hashtable.get(s);
            if (socket1 != self) {
                try {
                    printStream = new PrintStream(socket1.getOutputStream());
                    printStream.println(str);
                } catch (IOException e) {
                    // TODO: handle exception
                    e.printStackTrace();
                }
            }
        }
    }
    //窗口初始化方法
    public void init() {
        //textArea.setEditable(false);
        this.add(textArea);
        this.pack();
        this.addWindowListener(new WindowListener() {

            @Override
            public void windowOpened(WindowEvent arg0) {
                // TODO Auto-generated method stub

            }

            @Override
            public void windowIconified(WindowEvent arg0) {
                // TODO Auto-generated method stub

            }

            @Override
            public void windowDeiconified(WindowEvent arg0) {
                // TODO Auto-generated method stub

            }

            @Override
            public void windowDeactivated(WindowEvent arg0) {
                // TODO Auto-generated method stub

            }

            @Override
            public void windowClosing(WindowEvent arg0) {
                // TODO Auto-generated method stub
                System.exit(-1);
            }

            @Override
            public void windowClosed(WindowEvent arg0) {
                // TODO Auto-generated method stub

            }

            @Override
            public void windowActivated(WindowEvent arg0) {
                // TODO Auto-generated method stub

            }
        });
        this.setVisible(true);
        startServer();
    }

    //启动服务
    public void startServer() {
        // TODO Auto-generated method stub
        try {
            ServerSocket serverSocket = new ServerSocket(3333);
            //启动服务,一直等待客户端请求
            while (true) {
                socket = serverSocket.accept();
                //接受客户端请求之后,产生socket对象,交给多线程聊天服务处理
                Service ser = new Service(socket);
                new Thread(ser).start();
            }
        } catch (IOException e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }

    //定义内部类
    class Service implements Runnable {
        Socket socket = null;
        String name;
        public Service(Socket socket) {
            // TODO Auto-generated constructor stub
            this.socket = socket;
            try {
                BufferedReader b1 = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                name = b1.readLine();
                hashtable.put(name, socket);
            } catch (IOException e) {
                // TODO: handle exception
                e.printStackTrace();
            }
        }
        public Service() {
            // TODO Auto-generated constructor stub
        }
        @Override
        public void run() {
            // TODO Auto-generated method stub
            BufferedReader br = null;
            try {
                br = new BufferedReader(new InputStreamReader(socket.getInputStream()));  //得到输入流,可以得到客户端输出流
                boradCast(name+"进入聊天室\n", socket);
                //保证不断地从客户端获得输入流,并输出到屏幕上
                while (true) {
                    String str = "";
                    System.out.println("服务器"+socket.isClosed());
                    if ((str = br.readLine()) != null) {
                        boradCast(name+"说:"+str+"\n", socket);
                    }
                    //退出
                    if ("quit".equals(str)) {
                        hashtable.remove(name);
                        break;
                    }
                }
                br.close();
                socket.close();
                textArea.append("关闭连接"+name);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        CServer cServer = new CServer("服务器");
    }
}


CClient.java:

package Chat;

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.HeadlessException;
import java.awt.Label;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JFrame;

public class CClient extends JFrame{
    TextArea textArea = new TextArea(18, 50);
    TextField textField = new TextField(40);
    TextField nickname = new TextField(20);
    TextField address = new TextField("localhost", 10);
    TextField port = new TextField("3333", 5);
    Button sendBtn = new Button("发送");
    Button connBtn = new Button("连接");
    Panel panel1 = new Panel();
    Panel panel2 = new Panel();
    Socket socket = null;
    PrintStream printStream = null;
    public CClient() throws HeadlessException{
        // TODO Auto-generated constructor stub
        super();
        init();
    }
    public CClient(String string) throws HeadlessException{
        super(string);
        init();
    }
    public void init() {
        // TODO Auto-generated method stub
        this.add(textArea);
        panel1.add(new Label("地址"));
        panel1.add(address);
        panel1.add(new Label("端口号"));
        panel1.add(port);
        panel1.add(new Label("昵称"));
        panel1.add(nickname);
        panel2.add(connBtn);
        panel2.add(textField);
        panel2.add(sendBtn);
        sendBtn.addActionListener(new MyListener());
        connBtn.addActionListener(new connBtnListener());
        this.add(panel1, BorderLayout.NORTH);
        this.add(panel2, BorderLayout.SOUTH);
        System.out.println(this.getTitle());
        this.pack();
        this.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                PrintStream printStream;
                try {
                    printStream = new PrintStream(socket.getOutputStream());
                    printStream.println("quit");
                } catch (IOException e2) {
                    // TODO: handle exception
                    e2.printStackTrace();
                }
                close();
                System.exit(-1);
            }
        });
        this.setVisible(true);
        connect();  //连接服务器
    }
    public void close() {
        if (printStream != null) {
            printStream.close();
            try {
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException e) {
                // TODO: handle exception
                e.printStackTrace();
            }
        }
    }
    //连接服务器
    public void connect() {
        try {
            socket = new Socket(address.getText(), Integer.parseInt(port.getText()));
            this.setTitle(nickname.getText());
        } catch (IOException e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
    public void recive() {
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String string = "";
            while ((string = br.readLine()) != null) {
                textArea.append(string + "\n");
            }
        } catch (IOException e) {
            // TODO: handle exception
            System.exit(-1);
        }
    }
    //发送个人昵称到服务器
    public void sendName() {
        String name = nickname.getText();
        PrintStream printStream;
        try {
            printStream = new PrintStream(socket.getOutputStream());
            printStream.println(name);
        } catch (IOException e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
    class MyListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent arg0) {
            // TODO Auto-generated method stub
            try {
                PrintStream printStream =new PrintStream(socket.getOutputStream());
                printStream.println(textField.getText());
                textArea.append("我说:"+textField.getText()+"\n");
                textField.setText("");
            } catch (IOException e) {
                // TODO: handle exception
                e.printStackTrace();
            }
        }
    }

    class connBtnListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent arg0) {
            // TODO Auto-generated method stub
            connect();
            sendName();
            Recive r = new Recive();  //监听服务器消息
            new Thread(r).start();;
        }
    }

    class Recive implements Runnable {
        @Override
        public void run() {
            // TODO Auto-generated method stub
            recive();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // TODO: handle exception
                e.printStackTrace();
            }
        }   
    }
    public static void main(String[] args) {
        CClient cClient = new CClient("客户端");
    }
}

你可能感兴趣的:(Java)