Сравнение строк не работает, и пустой список не пустой
Я работаю над небольшой программой Server - Client. Приведенный здесь код работает в другой программе и работает нормально, но по какой-то причине в этой программе нет.
Поэтому, когда пользователь хочет войти в систему, он вводит свое имя пользователя и пароль, а затем это сообщение отправляется как "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.
Извините, это был такой длинный пост, но спасибо за то, что терпели это!
1 ответ
Проблема заключается в том, что connected
список содержит записи, когда он не должен содержать.
Вы должны выяснить, как это произошло. Посмотрите на код, который создает объект списка, и убедитесь, что вы не заполнили его неправильными данными. Список волшебным образом не получит записи из воздуха1. Если он не пустой, то ваш код поместил туда записи... где-то, как угодно.
Я также добавил бы некоторые записи, чтобы увидеть, что connected
содержит, и что userDat[0]
непосредственно перед кодом проверки дубликатов.
Наконец, поскольку вы упоминаете, что этот код является многопоточным:
- Проверьте, что есть только один
connected
и что все темы разделяют это. - Проверьте правильность синхронизации.
(Я подозреваю, что вы не синхронизируете должным образом. Это не может напрямую объяснить поведение, которое вы описали... connected
непустой, прежде чем кто-либо попытался войти в систему... но это может вызвать другие проблемы.)
Если это не поможет, то вам нужно будет предоставить MCVE, чтобы мы могли >> запустить<< ваш код, чтобы выяснить, что на самом деле здесь происходит.
1 - Хотя это теоретически возможно, я бы не принимал во внимание возможность ошибок в библиотеках классов или JVM.