簡體   English   中英

我的 Java 多線程 TCP 服務器經常崩潰

[英]Constant crashes with my Java Multi-threaded TCP Server

所以我知道這是一個有很多代碼的大問題,但我不知道問題是什么,因為登錄系統似乎工作正常,但是當我嘗試添加錯誤或查看錯誤時,它會使服務器崩潰,我必須重啟服務器:

import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class Server
{
    // User database
    private static Map<String, String> userDatabase = new HashMap<>();

    // Bug report database
    private static Map<Integer, String> bugDatabase = new HashMap<>();
    private static int nextBugId = 1;

    public static void main(String[] args) throws Exception
    {
        // Create a server socket
        ServerSocket welcomeSocket = new ServerSocket(6789);

        // Create a thread pool with a fixed number of threads
        Executor executor = Executors.newFixedThreadPool(10);

        while (true)
        {
            // Accept a new client connection
            Socket connectionSocket = welcomeSocket.accept();

            // Create a new thread for the client and submit it to the thread pool
            Runnable clientHandler = new ClientHandler(connectionSocket);
            executor.execute(clientHandler);
        }
    }

    // Inner class for handling client requests
    private static class ClientHandler implements Runnable
    {
        private Socket connectionSocket;
        private BufferedReader inFromClient;
        private DataOutputStream outToClient;

        public ClientHandler(Socket socket) throws Exception
        {
            connectionSocket = socket;
            inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
            outToClient = new DataOutputStream(connectionSocket.getOutputStream());
        }

        public void run()
        {
            try
            {
                // Read request from the client
                String request = inFromClient.readLine();

                if (request.startsWith("REGISTER"))
                {
                    // Parse the request
                    String[] tokens = request.split(" ");
                    String username = tokens[1];
                    String password = tokens[2];

                    // Check if the username is already taken
                    if (userDatabase.containsKey(username))
                    {
                        outToClient.writeBytes("ERROR: Username already taken\n");
                    }
                    else
                    {
                        // Add the user to the database
                        userDatabase.put(username, password);
                        outToClient.writeBytes("OK\n");
                    }
                }
                else if (request.startsWith("LOGIN"))
                {
                    // Parse the request
                    String[] tokens = request.split(" ");
                    String username = tokens[1];
                    String password = tokens[2];

                    // Check if the username and password are correct
                    if (!userDatabase.containsKey(username))
                    {
                        outToClient.writeBytes("ERROR: Invalid username\n");
                    }
                    else if (!userDatabase.get(username).equals(password))
                    {
                        outToClient.writeBytes("ERROR: Invalid password\n");
                    }
                    else
                    {
                        outToClient.writeBytes("OK\n");
                    }
                }
                else if (request.startsWith("ADD"))
                {
                    // Parse the request
                    String[] tokens = request.split(" ");
                    String appName = tokens[1];
                    String dateTimeStamp = tokens[2];
                    String platform = tokens[3];
                    String problemDesc = tokens[4];
                    String status = tokens[5];

                    // Add the bug report to the database
                    int bugId = nextBugId++;
                    bugDatabase.put(bugId, appName + " " + dateTimeStamp + " " + platform + " " + problemDesc + " " + status);
                    outToClient.writeBytes("OK " + bugId + "\n");
                }
                else if (request.startsWith("UPDATE"))
                {
                    // Parse the request
                    String[] tokens = request.split(" ");
                    int bugId = Integer.parseInt(tokens[1]);
                    String newStatus = tokens[2];

                    // Update the bug report in the database
                    if (updateBugStatus(bugId, newStatus))
                    {
                        outToClient.writeBytes("OK\n");
                    }
                    else
                    {
                        outToClient.writeBytes("ERROR: Invalid bug ID\n");
                    }
                }
                else if (request.startsWith("VIEW"))
                {
                    // Send all the bug reports to the client
                    for (int bugId : bugDatabase.keySet())
                    {
                        outToClient.writeBytes(bugId + " " + bugDatabase.get(bugId) + "\n");
                    }
                    outToClient.writeBytes("OK\n");
                }
                else if (request.startsWith("QUIT"))
                {
                    // Close the connection to the client
                    connectionSocket.close();
                }
                else
                {
                    // Print an error message if the request is invalid
                    outToClient.writeBytes("ERROR: Invalid request\n");
                }
            }
            catch (IOException ex)
            {
                System.out.println("Error: An I/O exception occurred");
            }
        }        // Helper method to update the status of a bug report in the database
        private boolean updateBugStatus(int bugId, String newStatus)
        {
            if (!bugDatabase.containsKey(bugId))
            {
                return false;
            }

            String[] bugDetails = bugDatabase.get(bugId).split(" ");
            bugDetails[4] = newStatus;
            bugDatabase.put(bugId, String.join(" ", bugDetails));
            return true;
        }
    }
}                           

import java.io.*;
import java.net.*;
import java.util.*;

public class Client
{
    public static void main(String[] args)
    {
        try
        {
            // Create a socket to connect to the server
            Socket clientSocket = new Socket("localhost", 6789);

            // Create input and output streams to read from and write to the server
            BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());

            // Read input from the user
            BufferedReader userInput = new BufferedReader(new InputStreamReader(System.in));

            while (true)
            {
                // Print a prompt to the user
                System.out.print("Enter a command (REGISTER, LOGIN, or QUIT): ");

                // Read the command from the user
                String command = userInput.readLine();

                if (command.equals("REGISTER"))
                {
                    // Read the username and password from the user
                    System.out.print("Enter a username: ");
                    String username = userInput.readLine();
                    System.out.print("Enter a password: ");
                    String password = userInput.readLine();

                    // Send the REGISTER command and the username and password to the server
                    outToServer.writeBytes("REGISTER " + username + " " + password + "\n");

                    // Read the response from the server
                    String response = inFromServer.readLine();
                    System.out.println(response);
                }
                else if (command.equals("LOGIN"))
                {
                    // Read the username and password from the user
                    System.out.print("Enter a username: ");
                    String username = userInput.readLine();
                    System.out.print("Enter a password: ");
                    String password = userInput.readLine();

                    // Send the LOGIN command and the username and password to the server
                    outToServer.writeBytes("LOGIN " + username + " " + password + "\n");

                    // Read the response from the server
                    String response = inFromServer.readLine();
                    System.out.println(response);

                    // If the login was successful, allow the user to add a bug report
                    if (response.equals("OK"))
                    {
                        while (true)
                        {
                            // Print a prompt to the user
                            System.out.print("Enter a command (ADD, UPDATE,VIEW ,or QUIT): ");

                            // Read the command from the user
                            String command2 = userInput.readLine();

                            if (command2.equals("ADD"))
                            {
                                // Read the bug report details from the user
                                System.out.print("Enter the application name: ");
                                String appName = userInput.readLine();
                                System.out.print("Enter the date and time stamp: ");
                                String dateTime = userInput.readLine();
                                System.out.print("Enter the platform: ");
                                String platform = userInput.readLine();
                                System.out.print("Enter the problem description: ");
                                String problem = userInput.readLine();
                                System.out.print("Enter the status (Open, Assigned, or Closed): ");
                                String status = userInput.readLine();

                                // Send the ADD command and the bug report details to the server
                                outToServer.writeBytes("ADD " + appName + " " + dateTime + " " + platform + " " + problem + " " + status + "\n");

                                // Read the response from the server
                                String response2 = inFromServer.readLine();
                                System.out.println(response2);
                            }
                            else if (command2.equals("UPDATE"))
                            {
                                // Read the bug report ID and new status from the user
                                System.out.print("Enter the bug report ID: ");
                                int bugId = Integer.parseInt(userInput.readLine());
                                System.out.print("Enter the new status (Open, Assigned, or Closed): ");
                                String newStatus = userInput.readLine();

                                // Send the UPDATE command and the bug report ID and new status to the server
                                outToServer.writeBytes("UPDATE " + bugId + " " + newStatus + "\n");

                                // Read the response from the server
                                String updateResponse = inFromServer.readLine();
                                System.out.println(updateResponse);
                            }
                            else if (command2.equals("VIEW"))
                            {
                                // Send the VIEW command to the server
                                outToServer.writeBytes("VIEW\n");

                                // Read the response from the server
                                String response2 = inFromServer.readLine();

                                // Print the bug reports received from the server
                                while (!response2.equals("OK"))
                                {
                                    System.out.println(response2);
                                    response2 = inFromServer.readLine();
                                }
                            }
                            else if (command2.equals("QUIT"))
                            {
                                // Send the QUIT command to the server
                                outToServer.writeBytes("QUIT\n");

                                // Close the connection to the server
                                clientSocket.close();

                                // Terminate the loop
                                break;
                            }
                            else
                            {
                                // Print an error message if the command is invalid
                                System.out.println("Invalid command");
                            }
                        }
                    }
                }
                else if (command.equals("QUIT"))
                {
                    // Send the QUIT command to the server
                    outToServer.writeBytes("QUIT\n");

                    // Close the connection to the server
                    clientSocket.close();

                    // Terminate the loop
                    break;
                }
                else
                {
                    // Print an error message if the command is invalid
                    System.out.println("Invalid command");
                }
            }
        }
        catch (UnknownHostException ex)
        {
            System.out.println("Error: Unable to connect to the server");
        }
        catch (IOException ex)
        {
            System.out.println("Error: An I/O exception occurred");
        }
        catch (NumberFormatException ex)
        {
            System.out.println("Error: Invalid input");
        }
    }
}




我只想簡單地做到這一點,以便將錯誤注冊到服務器,然后可以在客戶端顯示而不會出現任何崩潰

拋出的異常:

Exception in thread "main" java.net.SocketException: An established connection was aborted by the software in your host machine
    at java.base/sun.nio.ch.NioSocketImpl.implWrite(NioSocketImpl.java:420)
    at java.base/sun.nio.ch.NioSocketImpl.write(NioSocketImpl.java:440)
    at java.base/sun.nio.ch.NioSocketImpl$2.write(NioSocketImpl.java:826)
    at java.base/java.net.Socket$SocketOutputStream.write(Socket.java:1035)
    at java.base/java.net.Socket$SocketOutputStream.write(Socket.java:1031)
    at java.base/java.io.DataOutputStream.writeBytes(DataOutputStream.java:282)
    at Client.main(Client.java:83)

“已建立的連接被主機中的軟件中止”異常是客戶端注意到服務器進程已崩潰並關閉連接,同時寫入 Client.java:83。

從出現缺陷的服務器進程中查看崩潰信息會更有幫助。 但是即使沒有那個,我注意到您正在使用以空格分隔的協議,即:

客戶:

// Send the ADD command and the bug report details to the server
outToServer.writeBytes("ADD " + appName + " " + dateTime + " " + platform + " " + problem + " " + status + "\n");

服務器:

 else if (request.startsWith("ADD"))
 {
     // Parse the request
     String[] tokens = request.split(" ");
     String appName = tokens[1];
     String dateTimeStamp = tokens[2];
     String platform = tokens[3];
     String problemDesc = tokens[4];
     String status = tokens[5];

     // Add the bug report to the database
     int bugId = nextBugId++;
     bugDatabase.put(bugId, appName + " " + dateTimeStamp + " " + platform + " " + problemDesc + " " + status);
     outToClient.writeBytes("OK " + bugId + "\n");

但是,如果這些字段都不包含嵌入的空格字符,這可能只會按您的預期運行,如果包含,則它會拋出服務器對這些字段的解析。 並且您的新記錄中的尾隨單詞將被截斷。 服務器代碼中的其他地方也出現了同樣的假設/問題。

我不確定為什么這會導致實際崩潰,但您可能應該選擇一個更好的分隔符,它不太可能出現在字段值中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM