我目前正在编写一个简单的TCP聊天客户端服务器应用程序,它可以与套接字一起工作。客户端连接到服务器,一旦被接受,就会创建一个新的工作线程来侦听客户端输入。连接到服务器(端口8818处的本地主机)工作正常,但只要工作线程在登录后开始侦听更多客户端输入
a java.net.SocketException: Connection reset
抛出(请参见下面的堆栈跟踪)。我知道,此异常的一个可能来源可能是服务器或客户端未正确或强制关闭的套接字。因此,我的假设是,我没有正确处理关闭客户端套接字的操作,这会导致连接重置。
我想要实现的目标:
工作者侦听客户端输入,只要该输入不为null,就会处理请求(例如简单登录),否则,套接字将关闭(请参阅下面的代码摘录)。我的客户端从服务器收到一条“登录成功”消息,指示我的
handleLogin()
函数可以工作,但在没有收到来自客户端的更多输入后,服务器似乎只是重置,而不是关闭套接字,即使
clientSocket.close()
在while循环之后发出。
服务器Java语言
@Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(serverPort);
while (true) {
// Accept connection(s) from new chat client(s)
System.out.println("SERVER: WAITING TO ACCEPT CLIENT CONNECTIONS ...");
Socket clientSocket = serverSocket.accept();
System.out.println("SERVER: CONNECTION ACCEPTED FROM: " + clientSocket);
// Process client request in separate Thread
WorkerThread worker = new WorkerThread(this, clientSocket);
workerList.add(worker);
worker.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
WorkerThread。Java语言
@Override
public void run() {
try {
handleClientSocket();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void handleLogin(OutputStream outputStream, String[] tokens) throws IOException {
if (tokens.length != 3) {
outputStream.write("LOGIN FAILED!\n".getBytes());
return;
}
// Extract username and password from user input
String username = tokens[1];
String password = tokens[2];
if (username.equals("anna") && password.equals("anna")) {
outputStream.write("Login successful!\n".getBytes());
} else {
outputStream.write("Error logging in!\n".getBytes());
}
}
private void handleClientSocket() throws IOException, InterruptedException {
InputStream inputStream = clientSocket.getInputStream();
this.outputStream = clientSocket.getOutputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line;
// THIS IS WHERE THE EXCEPTION OCCURS AFTER CLIENT HAS LOGGED IN SUCCESSFULLY
while ((line = bufferedReader.readLine()) != null) {
String[] tokens = StringUtils.split(line);
if (tokens.length > 0 && tokens != null) {
String command = tokens[0];
// Evaluate the entered command and handle the request accordingly
if ("login".equalsIgnoreCase(command)) {
handleLogin(outputStream, tokens);
}
// process other commands ...
}
}
clientSocket.close(); // POSSIBLY WORNG WAY OF CLOSING THE CLIENT SOCKET?
}
客户Java语言
import java.io.*;
import java.net.Socket;
public class Client {
private final String serverName;
private final int serverPort;
private Socket mySocket;
private OutputStream serverOut;
private InputStream serverIn;
public Client(String serverName, int serverPort) {
this.serverName = serverName;
this.serverPort = serverPort;
}
private boolean connect() {
try {
mySocket = new Socket(serverName, serverPort);
serverOut = mySocket.getOutputStream();
serverIn = mySocket.getInputStream();
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
private void login(String username, String password) throws IOException {
String command = "login " + username + " " + password + "\n";
serverOut.write(command.getBytes());
}
public static void main(String[] args) throws IOException {
Client client = new Client("localhost", 8818);
if (client.connect()) {
System.out.println("Connection successful!");
client.login("anna", "anna");
} else {
System.err.println("Connection failed ...");
}
}
}
堆栈跟踪
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:189)
at java.net.SocketInputStream.read(SocketInputStream.java:121)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at WorkerThread.handleClientSocket(WorkerThread.java:70)
at WorkerThread.run(WorkerThread.java:45)
当我用PUTTY测试我的服务器时(即通过连接到localhost,然后在PUTTY的终端中发出命令),一切正常。
我对socket编程还是相当陌生的,所以这里可能也有一个逻辑缺陷。任何帮助都将非常感谢,因为我真的很想继续这个项目。
提前感谢!