java socket聊天室 swing做界面 Tcp为通讯协议 支持私聊 群聊 发文件

                        Java的的的的聊天室


           源代码下载

            首先我们来看看程序界面,丑到爆!!!,勉强能用就行啦

           第一个:登录界面

                     java socket聊天室 swing做界面 Tcp为通讯协议 支持私聊 群聊 发文件_第1张图片


              第二个:用户界面

                         java socket聊天室 swing做界面 Tcp为通讯协议 支持私聊 群聊 发文件_第2张图片


                   第三个:服务器界面

            

               java socket聊天室 swing做界面 Tcp为通讯协议 支持私聊 群聊 发文件_第3张图片


          好了上面三个界面是程序的主界面,下面我们先讲讲如何使用源代码

             使用条件:一数据库,我这里用的MySQL的的的数据库,如果使用其他数据库比如甲骨文

                                      需要去cn.scau.util包的DBproperties配置文件中重新配置数据库参数

                                                    我们来看看原来的配置java socket聊天室 swing做界面 Tcp为通讯协议 支持私聊 群聊 发文件_第4张图片

                              比如username password url使用jdbc的朋友应该更懂,还有自己导入对应数据库的驱动包


                                 二。数据库中所用到的表

                                                                  首先看看表结构java socket聊天室 swing做界面 Tcp为通讯协议 支持私聊 群聊 发文件_第5张图片

                                                                  说明一下各个字段的类型:

                                                               字段类型

                                                        register_time:TIMESTAMP

                                                                                   用户名:VARCHAR

                                                          密码:VARCHAR

                                                          昵称:VARCHAR

                                                           USER_ID:INT

                                           所以要建立chatuser表先,再在配置文件DBproperties中配置数据库


                      三:我是用的netbeans的编写的,如果用的NetBeans的导入项目的话,再满足上面两个条件就可以运行啦


   好了讲完使用,我们来说说程序的整体思路

      首先看看客户端和服务端的流程图

java socket聊天室 swing做界面 Tcp为通讯协议 支持私聊 群聊 发文件_第6张图片


    什么意思呢?我来解释一下

   首先,图中有三个类,一个方法。三个类分别是:ServerThread,ClientThreadMessageThread

                  一个方法: conServer

   其中:ServerThread,ClientThread属于服务器的类,而MessageThread,conServer属于客户端

 

   最后:依照流程图,首先客户端的conServer,发起向服务端的连接,服务端的ServerThread是提前开

      启的,ServerThread线程接受客户端的连接,新建一个ClientThread线程为这个新连接的客户端服务

      这里的服务是接受这个客户端的信息,和向这个客户端发送信息,同时呢,在遥远的青青草原

      上的客户端也会开启一个线程,它就是MessageThread,专门用来接收来自服务端对应的           ClientThread线程发来的消息。


      为什么这样呢,因为这样服务端每次接收到新的客户端的连接,就会为它分配一个ClientThread线程

      我们在服务端维护这个ClientThread线程列表,就可以区分每个客户端了,由于每个客户端在服务器

      都有一个对应的ClientThread线程,所以客户端发送的信息也不会乱。


最后我们来看看流程图中的代码,也是这个聊天室的核心


  //服务器线程,用来接收用户登录
    class ServerThread extends Thread {

        private boolean ifopen;

        private ServerSocket serverSocket;

        public ServerThread() {
            this.ifopen = true;
        }

        @Override
        public void run() {
            try {
                serverSocket = new ServerSocket(port);
                JOptionPane.showMessageDialog(su.getJframe(), "服务器成功启动");
                while (ifopen) {
                    Socket clnSocket = serverSocket.accept();//阻塞接收客户端的连接
                    if (userList.size() == max) {

                        su.getShowMessage().append("有客户端尝试连接服务端,但在线人数已达上限" + ServerUtil.getTime() + "\r\n");

                        clnSocket.close();
                        continue;
                    }

                    //每个客户端都有对应的线程处理
                    ClientThread client = new ClientThread(clnSocket);
                    su.getListModel().addElement(client.user.getName());//用户列表更新
                    userList.put(client.getUser().getName(), client);
                    client.start();
                }

            } catch (BindException be) {
                JOptionPane.showMessageDialog(su.getJframe(), "端口已经被占用,请重新启动!", "error", JOptionPane.ERROR_MESSAGE);
                return;
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }

        public ServerSocket getServerSocket() {
            return serverSocket;
        }

        public void setIfopen(boolean ifopen) {
            this.ifopen = ifopen;
        }
    }

    //
    /*
    每个连接到服务器的Client,都有一个线程来单独处理,接受消息
     */
    class ClientThread extends Thread {

        private ObjectOutputStream oos;
        private ObjectInputStream ois;
        private Socket socket;
        private User user;
        private boolean ifopen;

        public void PrivateSend(String message) {

        }
//        每个客户端对应一个客户端线程处理

        public ClientThread(Socket socket) {
            this.ifopen = true;
            this.socket = socket;
            try {
                ois = new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
                oos = new ObjectOutputStream(socket.getOutputStream());
                Object obj = ois.readObject();//读取用户信息包------------------------------------读取包

                DataBag db = (DataBag) obj;//取得数据包,第一个数据包存储了用户的信息
                this.user = db.getUser();//首先得到登录用户的信息

                //通知其他客户端,新用户上线
                BagTarget bt = new BagTarget();
                bt.setOption(GROUP_CHAT);
                bt.setGroupOption(USER_ADD);
                db.setBt(bt);//----------------------3目的地数据
                GroupSend(db);//--------------------------------------------向其他在线用户群发有新的用户登录包

                //向刚登录的用户发送当前在线的用户列表
                if (userList.size() > 0) {
                    DataBag dblist = new DataBag();
                    HashMap onlineUser = new HashMap();
                    Iterator iter = userList.entrySet().iterator();

                    while (iter.hasNext()) {

                        Map.Entry entry = (Map.Entry) iter.next();
                        String key = (String) entry.getKey();

                        ClientThread val = (ClientThread) entry.getValue();
                        onlineUser.put(key, val.getUser());
                    }
                    dblist.setUserlist(onlineUser);//-----------------------4在线的用户
                    BagTarget btList = new BagTarget();
                    btList.setOption(GROUP_CHAT);
                    btList.setGroupOption(USER_LIST);
                    dblist.setBt(btList);//曾经的bug出错点-------------------------------------bug     bug           bug------------------------------>
                    oos.writeObject(dblist);
                    oos.flush();

                }

            } catch (Exception ex) {
                System.out.println(ex.getMessage());
                ex.printStackTrace();
            }

        }


  //<----------------------------------------消息接收类---------------------------------------------->
    //全天候接受信息

    class MessageThread extends Thread {

        private boolean ifopen;

        public MessageThread() {
            this.ifopen = true;
        }

        @Override
        public void run() {
            try {
                oos = new ObjectOutputStream(socket.getOutputStream());
                ois = new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
                //先发送自身的信息给服务器
                DataBag db = new DataBag();
                db.setUser(user);
                oos.writeObject(db);
                oos.flush();

                while (ifopen) {

                    Object obj = ois.readObject();

                    db = (DataBag) obj;
                    int option = db.getBt().getOption();//判断是私聊还是群聊
                    switch (option) {
                        case GROUP_CHAT:
                            GroupChat(db);
                            break;
                        case PRIVATE_CHAT:
                            PrivateRecv(db);
                            break;
                        default:
                    }

                }
            } catch (Exception ex) {
                System.out.println(ex.getMessage());
                ex.printStackTrace();
            }

        }




各位看官有问题的话请评论留言,我有空就过来回答










                                    


                                     

 

                              


                

你可能感兴趣的:(socket编程)