Java Socket客户端向服务器传输账号密码并验证返回布尔值故障排查
问题:客户端登录信息无法传输到服务器,服务器未获取到用户名和密码
核心原因
客户端代码中,Socket、DataInputStream、DataOutputStream是在main方法的局部作用域内创建的,loginMessage()方法根本无法访问这些对象。加上所有catch块都直接吞掉异常,导致空指针错误被隐藏,数据完全没有发送到服务器,服务器则一直阻塞在readUTF()步骤,表现为未获取到值。
修复步骤
1. 将Socket、数据流改为类成员变量
在客户端类(比如MyApplication)顶部添加成员变量,让loginMessage()能访问到通信对象:
// MyApplication类的成员变量声明 private Socket socket; private DataInputStream din; private DataOutputStream dout;
2. 在main方法中初始化成员变量
把原来main方法里的局部变量赋值给成员变量,而非创建局部变量:
public static void main(String[] args) { MyApplication x = new MyApplication(); // 先创建实例,再初始化通信对象 try { x.socket = new Socket("127.0.0.1", 7000); x.din = new DataInputStream(x.socket.getInputStream()); x.dout = new DataOutputStream(x.socket.getOutputStream()); } catch (Exception e) { e.printStackTrace(); // 打印异常,方便调试 } // 后续线程启动逻辑保持不变 Progress a = new Progress(); Secondpage s = new Secondpage(); Thread t1 = new Thread(x); t1.start(); try { t1.join(); } catch (Exception e) { e.printStackTrace(); } a.start(); try { a.join(); } catch (Exception e) { e.printStackTrace(); } s.start(); try { s.join(); } catch (Exception e) { e.printStackTrace(); } }
3. 修改loginMessage()的异常处理与数据发送
去掉空catch块,打印异常信息,同时调用flush()确保数据立即发送:
private void loginMessage() { String uName = txtUsername.getText(); try { dout.writeUTF(uName); dout.flush(); // 强制发送缓冲区数据 } catch (Exception e) { e.printStackTrace(); } String password = new String(usPassword.getPassword()); try { dout.writeUTF(password); dout.flush(); } catch (Exception e) { e.printStackTrace(); } try { boolean loginSuccess = din.readBoolean(); if (loginSuccess) { JOptionPane.showMessageDialog(this, "Thank you for logging in " + uName + ". You will now get redirected to our Customer Zone, where you can make purchases. Press OK to continue.", "Success!", JOptionPane.INFORMATION_MESSAGE); finished = true; } else { JOptionPane.showMessageDialog(this, "Error. Either your username or password is incorrect. Please try again.", "Error", JOptionPane.ERROR_MESSAGE); } } catch (Exception e) { e.printStackTrace(); } }
4. 服务器端优化(可选)
为避免服务器无限等待客户端数据,给Socket设置超时:
public static void main(String[] args) { try { ServerSocket serverSocket = new ServerSocket(7000); System.out.println("Waiting for a client..."); Socket mySocket = serverSocket.accept(); mySocket.setSoTimeout(10000); // 设置10秒超时 System.out.println("I have a client"); DataInputStream clientIn = new DataInputStream(mySocket.getInputStream()); DataOutputStream clientOut = new DataOutputStream(mySocket.getOutputStream()); uname = clientIn.readUTF(); pwd = clientIn.readUTF(); System.out.println("Received username: " + uname + ", password: " + pwd); boolean verif = verifyUserLogin(uname, pwd, filepath, sep); clientOut.writeBoolean(verif); clientOut.flush(); System.out.println("Verification result sent: " + verif); } catch (Exception e) { e.printStackTrace(); // 打印完整异常栈 } }
额外注意事项
- 禁止使用空catch块吞掉异常,至少打印异常信息,否则调试会非常困难
- 写入数据流后调用
flush(),避免数据滞留在缓冲区 - 服务器
verifyUserLogin方法中,需处理文件不存在、行格式错误的情况,防止数组越界
内容的提问来源于stack exchange,提问作者whiffed
相关产品推荐
相关产品推荐

