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]、「重複チェック」コードの直前に何があるかを確認します。

最後に、このコードはマルチスレッドであると述べたので:

  • 1 つしかないことconnected、およびすべてのスレッドがそれを共有していることを確認してください。
  • 正しく同期されていることを確認してください。

(適切に同期していないと思われます。それは、あなたが説明した動作を直接説明するものではありません...connected誰かがログインしようとする前に空ではない...しかし、他の問題を引き起こす可能性があります。)

これで問題が解決しない場合は、実際に何が起こっているかを理解するためにコードを >>実行<< できるように、 MCVEを提供する必要があります。


1 - 理論的には可能ですが、クラス ライブラリまたは JVM にバグが発生する可能性は無視します。

于 2016-05-02T03:22:56.837 に答える