正在努力学习的小白袁 2023-07-25 11:01 采纳率: 90%
浏览 22
已结题

java网络编程当两个用户先后登录连接到服务端,先者登录手动强制退出,但后登录发生Connect reset异常的问题

我正在写一个类似QQ通信系统的程序,但是遇到这样一个问题:
qq中不能同时登陆一个账号,如果这个账号被1端登陆上,但2端也想登陆上,这时候1端被强制退出,于是2端成功登陆上,就避免了两个账号同时登陆的问题
但是我在写程序的时候,发现2端在登陆后,1端确实被强制退出了,2端和服务端抛出了异常:SokectException :Connect Reset
我不清楚这是为什么,代码里 if (newUser != null)代码块是我主题
以下是我的代码

public QQServer() throws IOException {
        try {
            while (true) {
                //得到一个客户端输入的Socket
                Socket socket = sockets.accept();
                //得到一个对象流
                ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
                User user = (User) objectInputStream.readObject();

                //这里是注册操作
                //检查是否是要操作注册的用户:看看这个用户的id是否为空,如果为0,则是
                if (user.getId() == 0) {
                    //得到对应的Socket
                    System.out.println("用户请求注册账户");
                    RegisterAccount(user, socket);
                    continue;
                }

                //下面是登陆操作
                //验证账号密码
                int id = user.getId();
                String password = user.getPassword();
                Message message = new Message();
                //连接数据库,得到一个User类对象
                User newUser = CheckLogin(id, password);
                message.setUser(newUser);
                //如果这个对象存在
                if (newUser != null) {
                    //下面是验证这个用户是否在线,如果在线,那么在线的那一端就被强制下线,这一点就是新登录的线程
                    if(CheckOnline(user)!=null){
                        QQClientConnectServerThread qqClientConnectServerThread = ManageConnectThread.getHashMapSocket(user.getId());
                        Message message1 = new Message();
                        message1.setMessageType(MessageType.MESSAGE_EXIT);
                        //得到一直在登录的Socket
                        Socket socket1 = qqClientConnectServerThread.getSocket();
                        //从hashmap中删除这个线程
                        ManageConnectThread.RemoveHashMapSocket(user.getId());
                        //发送
                        new ObjectOutputStream(socket1.getOutputStream()).writeObject(message1);
                        //关闭这个Socket
                        //socket1.close();
                    }
                     //新的一端成功登陆上
                    message.setMessageType(MessageType.MESSAGE_LOGIN_SUCCESS);
                    //创建一个线程类
                    QQClientConnectServerThread qqClientConnectServerThread = new QQClientConnectServerThread(id, socket);
                    //将该线程放到hashmap
                    ManageConnectThread.addHashMapSocket(id, qqClientConnectServerThread);

                    //将该登陆的账号和姓名插入到OnlineUser里面去
                    String sql = "insert into onlineUser values(?,?)";
                    userDao.QueryDML(sql, newUser.getId(), newUser.getName());

                    //启动该线程
                    new Thread(qqClientConnectServerThread).start();

                    //新建一个对象输出流,将message发送过去
                    ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
                    objectOutputStream.writeObject(message);

                    System.out.println(user.getId() + "已登录系统");

                } else {
                    message.setMessageType(MessageType.MESSAGE_LOGIN_FAIL);
                    //新建一个对象输出流,将message发送过去
                    ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
                    objectOutputStream.writeObject(message);
                    socket.close();
                }
            }

        } catch (IOException | SQLException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                sockets.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


  • 写回答

2条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-07-25 13:11
    关注
    不知道你这个问题是否已经解决, 如果还没有解决的话:
    • 以下回答由chatgpt基于相关博客总结生成:

      由于没有给出具体的代码,我无法直接分析问题的具体原因和解决方案。但是,根据问题描述和参考资料,我可以提供一些可能的解决方案供你参考:

      1. 异常处理: 确保你的代码中针对网络连接异常进行了适当的处理。在Java网络编程中,可以使用try-catch块来捕获和处理异常。你可以捕获SocketException,然后根据具体的异常信息进行处理。例如,当捕获到Connect Reset异常时,可以简单地忽略该异常并继续运行程序。

      2. 连接管理: 确保你在程序中正确管理和关闭网络连接。当用户登录成功后,可以为每个用户创建一个独立的Socket连接,并保存在一个连接池中。当发生账号强制退出的情况时,可以通过关闭对应的连接来实现。同时,确保在连接池中及时删除已关闭的连接,以防止后续操作出现异常。

      3. 用户登录控制: 在程序中包含一个用户登录管理的模块,用于控制同一账号的多次登录。当一个用户尝试登录时,你可以在登录过程中检查当前账号是否已经被其他用户登录,并根据需要采取相应的措施。例如,当检测到同一账号已经被其他用户登录时,可以发送一个强制退出的消息给之前登录的用户,并关闭对应的连接。

      4. 多线程处理: 确保你的程序能够支持并发登录和连接操作。在Java中,可以使用多线程来实现这一点。当一个用户尝试登录时,可以将该操作放到一个独立的线程中进行处理,以便同时处理其他用户的登录请求。同时,对于用户的连接操作,也可以为每个连接创建一个独立的线程来处理,以防止线程阻塞导致登录操作无法进行。

      这些只是一些可能的解决方案,具体的实现方式需要根据你的代码和业务逻辑来决定。如果你能提供更多的代码和相关信息,我可以给出更具体的建议。


    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 10月11日
  • 已采纳回答 10月3日
  • 创建了问题 7月25日

悬赏问题

  • ¥15 机器学习预测遇到的目标函数问题
  • ¥15 python的EOFError该怎么解决?
  • ¥15 Fluent,液体进入旋转区域体积分数不连续
  • ¥15 java linux下将docx文件转pdf
  • ¥15 maven无法下载依赖包
  • ¥15 关于pycharm, Callable[[str],bool]作为方法参数使用时, lambda 类型不提示问题
  • ¥15 layui数据重载无效
  • ¥15 寻找了解qq家园纵横四海的程序猿。
  • ¥15 optisystem
  • ¥15 VB.NET画图时的撤销编程