0

我正在开发一个小型服务器 - 客户端程序。我在这里的代码也可以在不同的程序中运行并且工作正常,但由于某种原因在这个程序中没有。

因此,当用户想要登录时,他们输入他们的用户名和密码,然后此消息将作为“loginreq user:pass”发送到服务器套接字。

尽管客户显然不是问题(我认为),但我会为您提供代码:

private static void loginreq(){
    String User = null;
    String Pass = null;
    try {
        User = bufferRead.readLine();
        WriteOut(ANSI_RESET+"Password: " + ANSI_GREEN);
        Pass = bufferRead.readLine();
        WriteOut(ANSI_RESET);
    } catch (IOException e1) {
        e1.printStackTrace();
    }
    int serverPort = 6880;
      String ip = Server;
      String data = "loginreq " + User + ":" + Pass;
    try{ 
        Socket s = new Socket(ip, serverPort); 
        DataInputStream input = new DataInputStream( s.getInputStream()); 
      DataOutputStream output = new DataOutputStream( s.getOutputStream());
      if(s.isConnected()){
          //Step 1 send length
          System.out.println("Length"+ data.length());
          output.writeInt(data.length());
          //Step 2 send length
          System.out.println("Writing.......");
          output.writeBytes(data); // UTF is a string encoding

          //Step 1 read length
          int nb = input.readInt();
          byte[] digit = new byte[nb];
          //Step 2 read byte
          for(int i = 0; i < nb; i++){
            digit[i] = input.readByte();
          }
          String st = new String(digit);
      System.out.println("Received: "+ st);
    } else {
        WriteOut("Failed to connect to the server: "+Server+ "No Server");
    }
    }
    catch (UnknownHostException e){ 
        WriteOut("Sock:"+e.getMessage());
    }
    catch (EOFException e){
        WriteOut("EOF:"+e.getMessage()); 
    }
    catch (IOException e){
        WriteOut("IO:"+e.getMessage());
    }
}

以上获取用户名和密码并按照我之前解释的方式发送。

然后服务器做到了它的神奇(或缺少)服务器代码:

//Step 1 read length
          int nb = input.readInt();
          byte[] digit = new byte[nb];
          //Step 2 read byte
           String st =null;
          for(int i = 0; i < nb; i++){
            digit[i] = input.readByte();

           st = new String(digit);
          }
          ServerOut("Recieved : " + ANSI_CYAN +
            clientSocket.getInetAddress() + ANSI_RESET + " - " + st);
            if (st.startsWith("loginreq ")){ //login attempt
                ServerOut("[" + Server.getTimeNow() + "] "+getThreadInfoString() +" Proccessing login request from: " + clientSocket.getInetAddress());
                try(BufferedReader br = new BufferedReader(new FileReader("users.txt"))) {
                    st = st.replaceFirst("loginreq ", "");
                    for(String line; (line = br.readLine()) != null; ) {
                        if(st.equals(line)){
                            String[] userDat = st.split(":");
                            boolean duplicate = false;
                            if(!connected.isEmpty()){
                            for(User u : connected){
                                if (u.getUsername().equals(userDat[0])){
                                    duplicate = true;
                                    break;
                                } else {

                                }
                            }
                            }
                            if (duplicate){
                                ServerOut("[" + Server.getTimeNow() + "] "+getThreadInfoString() +" User rejected (duplicate) " + userDat[0] + " : " + clientSocket.getInetAddress());
                                clientReturn("User was already logged in!");
                            } else {
                                User user = new User(clientSocket.getInetAddress().toString(), userDat[0], (int) time);
                                connected.add(user);
                                ServerOut("[" + Server.getTimeNow() + "] "+getThreadInfoString() + " User: '" + userDat[0] + "' logged in with ip: " + clientSocket.getInetAddress());
                                clientReturn("Login accepted!");
                            }
                            break;
                        }
                    }
                } catch (Exception ex){
                    clientReturn("Server ran into an error!");
                    ex.printStackTrace();
                }
            }

这会读取客户端输入,如果它以“loginreq”开头,然后将其删除并分隔字符串,以便 userDat[0] 是用户名, userDat[1] 是密码。至此,它已经验证了用户存在。然后,如果有用户连接(我刚刚启动了服务器,所以没有任何用户),它会确定同一个用户是否已经登录,由于某种原因,这似乎返回 true。然后它返回到客户端,用户已经登录。这不仅是一个问题,而且虽然使用 ServerOut 的初始启动代码正确打印到控制台,但现在它在一个新线程中,它似乎根本不打印。我怀疑这可能是因为我使用的是 Jansi 控制台而不是 IDK。

抱歉,这篇文章太长了,但感谢您的耐心等待!

4

1 回答 1

0

问题似乎是connected列表包含不应该包含任何条目的条目。

你需要弄清楚这是怎么发生的。查看创建列表对象的代码,并检查您是否没有用错误的内容预填充它。列表不会凭空获得条目1。如果它不为空,那么您的代码已将条目放在那里……不知何故。

我还将添加一些日志记录以查看connected包含的内容以及userDat[0]“重复检查”代码之前的内容。

最后,既然您提到此代码是多线程的:

  • 检查是否只有一个connected并且所有线程都共享它。
  • 检查您是否正确同步它。

(我怀疑你没有正确同步。这不会直接解释你描述的行为......connected在任何人尝试登录之前非空......但它可能会导致其他问题。)

如果这没有帮助,那么您将需要提供一个MCVE,以便我们可以>>运行<<您的代码来弄清楚这里实际发生了什么。


1 - 虽然理论上是可能的,但我会忽略类库或 JVM 中出现错误的可能性。

于 2016-05-02T03:22:56.837 回答