【问题标题】:How do I fixed skipped input/output lines in Java Echo Server?如何修复 Java Echo Server 中跳过的输入/输出行?
【发布时间】:2021-11-13 02:09:30
【问题描述】:

网络计算新手,请原谅我的无知:

除了 /caesarcipher 之外,我的所有命令都可以工作 - 当我输入它时,直到客户端的下一条消息我才会收到回显,并且服务器直到 2 条后续消息才开始执行该功能已发送。

任何帮助将不胜感激!

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

public class EchoServer{

    public static void main(String[] args) throws Exception {
        //Initializes and attempts to connect server
        ServerSocket serverSock = null;
        try{
            serverSock = new ServerSocket(8000);
        }
        catch (IOException ie){
            System.out.println("[SERVER DISCONNECTED!] Can't listen on 8000");
            System.exit(1);
        }
        Socket link = null;
        System.out.println("[SERVER CONNECTED!] Listening for connection ...");
        try {
            link = serverSock.accept();
        }
        catch (IOException ie){
            System.out.println("[SERVER DISCONNECTED!] Accept failed");
            System.exit(1);
        }

        //Connects client if handshake is successful
        System.out.println("[CLIENT CONNECTED!] Link Information:" + link);
        System.out.println("Listening for input ...");

        //Initializes input and output streams
        PrintWriter output = new PrintWriter(link.getOutputStream(), true);
        BufferedReader input = new BufferedReader(new InputStreamReader(link.getInputStream()));
        String inputLine;
        while ((inputLine = input.readLine())!=null) {
            String currentMessage = inputLine;
            System.out.println("[SERVER:] " + currentMessage);
            switch(currentMessage){
                case "/myip":                                           //Looks up local IP address of client
                    MyLocalIPAddress myIP = new MyLocalIPAddress();
                    String ip = myIP.run();
                    output.println(ip);
                    System.out.println(ip);
                    break;
                case "/iplookup":                                       //Looks up IP of user input website
                    IPFinder ipFinder = new IPFinder();
//  TO DO:              UrlValidator validator = new UrlValidator();
                    System.out.println("[REQUESTING URL FROM CLIENT!]");
                    output.println("Enter Website URL:");
                    inputLine = input.readLine();
                    System.out.println("Server: " + inputLine);
//  TO DO:          if(validator.isValid(inputLine)) {                    //Regex to validate user input
                    String ipAddress = ipFinder.find(inputLine) + " ==>  [IPLOOKUP TERMINATING]";
                    System.out.println(ipAddress);
                    output.println(ipAddress);
                    System.out.println("[IPLOOKUP FUNCTION TERMINATING!]");
                    break;

                case "/numbergame":                                         //Starts a number guessing game
                    boolean isPlaying;
                    int randomNumber = -1;
                    final int maxNum = 100;
                    System.out.println("[CLIENT HAS INITIATED GUESS THE NUMBER GAME!]");
                    output.println("Would you like to play the number game (Y/N)?");
                    inputLine = input.readLine();
                    if(inputLine.equalsIgnoreCase("Y")){
                        System.out.println("[CLIENT REQUESTS TO BEGIN A GAME!]");
                        isPlaying = true;
                        System.out.println("[SERVER IS PICKING A RANDOM NUMBER!]");
                        output.println("Enter A Number Between 0-100 (/endgame to quit)");
                        randomNumber = (int) Math.floor(Math.random() * maxNum + 1);
                        System.out.println("[RANDOM NUMBER IS: " + randomNumber + "]");
                    }else if(inputLine.equalsIgnoreCase("N")){
                        System.out.println("[GUESS THE NUMBER GAME ABORTING]");
                        output.println("Quitting guess the number game");
                        isPlaying = false;
                    }else{
                        System.out.println("[CLIENT PROVIDED FAULTY INPUT, GAME ABORTING!]");
                        output.println("Input not recognized, game aborting!");
                        isPlaying = false;
                    }

                    while(isPlaying) {
                        System.out.println("[REQUESTING NUMBER FROM CLIENT!]");
                        inputLine = input.readLine();
                        if (inputLine.equalsIgnoreCase("/endgame")) {
                            isPlaying = false;
                        }
                        if (isNumeric(inputLine)) {
                            int currentGuess = Integer.parseInt(inputLine);
                            if (randomNumber == currentGuess) {
                                System.out.println("[CLIENT HAS GUESSED THE CORRECT NUMBER, GAME TERMINATING!]");
                                output.println("You have guessed correctly! Game ending!");
                                isPlaying = false;
                            } else if (currentGuess > randomNumber) {
                                System.out.println("[CLIENT GUESSED TOO HIGH!]");
                                output.println("Too high! Guess again!");
                            } else if (currentGuess < randomNumber) {
                                System.out.println("[CLIENT GUESSED TOO LOW!]");
                                output.println("Too low! Guess again!");
                            }
                        }else if(inputLine.equalsIgnoreCase("/endgame")){
                            System.out.println("[CLIENT HAS REQUESTED TO END GAME - TERMINATING...]");
                            output.println("Quitting game, better luck next time!");
                            break;

                        }else{
                            System.out.println("[CLIENT HAS PROVIDED INCORRECT INPUT]");
                            output.println("You have not entered a valid number, try again!");
                        }
                    }
                    break;

                case "/caesarcipher":
                    int maxKeyValue = 25;

                    int randomKey = (int) Math.floor(Math.random() * maxKeyValue + 1);
                    System.out.println("[CLIENT HAS INITIATED CAESAR CIPHER PROGRAM ----- CLIENT CAESAR CIPHER IS "
                            + randomKey + " (Type 'bye' to exit)!]");
                    output.println("Your Caesar Cipher is " + randomKey + ". Enter a message to encrypt: ");

                    while((inputLine = input.readLine()) != null) {
                        if (inputLine.equalsIgnoreCase("/caesarcipher")) {
                            output.println("Your Caesar Cipher is " + randomKey + ". Enter a message to encrypt: ");
                            output.flush();
                        }else if (inputLine.equalsIgnoreCase("/bye") ||
                                inputLine.equalsIgnoreCase("bye")) {
                            System.out.println("[CLIENT HAS REQUESTED TO END CAESAR CIPHER MODE!]");
                            output.println("Quitting Caesar cipher mode...");
                            break;
                        }else{
                            CaesarCipher caesarCipher = new CaesarCipher();
                            currentMessage = input.readLine();
                            String decryptedMessage = caesarCipher.decrypt(currentMessage, randomKey);
                            System.out.println("[SERVER:] Received: " + currentMessage + " ==> " +
                                    decryptedMessage);
                        }
                    }

                    break;

            

                case "/killserver":
                    System.out.println("[CLIENT REQUESTED SERVER SHUTDOWN!]");
                    TimeUnit.SECONDS.sleep(1);
                    System.out.println("[SERVER IS SHUTTING DOWN!");
                    TimeUnit.SECONDS.sleep(1);
                    closeServer(output, input, link, serverSock);
                    System.exit(1);
                    break;

                case "exit":
                case "quit":
                case "disconnect":
                    disconnectClient(output, input, link, serverSock);
                    break;
                default:
                    output.println(currentMessage);
            }
        }
    }
    public static void closeServer(PrintWriter output, BufferedReader input, Socket link, ServerSocket serverSock)
            throws IOException {
        System.out.println("[CLIENT REQUESTED TO CLOSE SERVER!");
        output.close();
        input.close();
        link.close();
        serverSock.close();
    }

    public static void disconnectClient(PrintWriter output, BufferedReader input, Socket link, ServerSocket serverSock)
            throws IOException, InterruptedException {
        output.println("[CLIENT REQUESTED TO CLOSE CONNECTION!");
        TimeUnit.SECONDS.sleep(5);
        output.println("[DISCONNECTING!");
        output.close();
        input.close();
        link.close();
    }

    //Tests to see if a string contains all numeric values
    public static boolean isNumeric(String str) {
        for (char c : str.toCharArray()){
            if (!Character.isDigit(c)) return false;
        }
        return true;
    }
}
import java.io.*;
import java.net.*;

public class EchoClient{
    public static void main(String[] args) throws IOException{
        Socket link = null;
        PrintWriter output = null;
        BufferedReader input = null;
        Boolean cipherModeActive = true;

        try{
            System.out.println("[CONNECTING TO SERVER ON PORT 8000]");
            link = new Socket(InetAddress.getLocalHost(), 8000);
            output = new PrintWriter(link.getOutputStream(), true);
            input = new BufferedReader(new InputStreamReader(link.getInputStream()));
            System.out.println("[CONNECTED TO SERVER]");
        }
        catch(UnknownHostException e)
        {
            System.out.println("Unknown Host");
            System.exit(1);
        }
        catch (IOException e){
            System.out.println("Cannot connect to host");
            System.exit(1);
        }

        BufferedReader stdIn = new BufferedReader((new InputStreamReader(System.in)));
        String usrInput;

        System.out.println("Welcome to the Server!\n\n" +
                "----- Here is a List Options: ----- \n " +
                "/myip ----- will allow you to look up your ip address\n" +
                "/iplookup ----- will allow you to look up the ip of a URL\n" +
                "/numbergame ----- allows you to play a guess the number game\n" +
                "/caesarcipher ----- allows you to encrypt and decrypt server messages using a caesar cipher\n" +
                "/exit, /quit, /disconnect ---- allows you to disconnect from the server\n\n" +
                "Enter a message:");

        //User Input
        boolean cipherActive = false;
        while ((usrInput = stdIn.readLine())!=null){
            output.println(usrInput);
            String message = input.readLine();

            if(usrInput.equalsIgnoreCase("/caesarcipher")){
                cipherActive = true;
            }

            if(!cipherActive){
                System.out.println("echo: " + message);
                output.flush();
            }
            if(cipherActive) {
                CaesarCipher caesarCipher = new CaesarCipher();
                String serverKeyMessage = message;
                int serverKey = Integer.parseInt(serverKeyMessage.replaceAll("[^0-9]", ""));
                while ((usrInput = stdIn.readLine()) != null) {
                    message = usrInput;
                    if (usrInput.equalsIgnoreCase("/caesarcipher")){
                        output.flush();
                    }else if (usrInput.equalsIgnoreCase("/bye")
                            || usrInput.equalsIgnoreCase("bye")) {
                        break;
                    }
                    //Encrypts message to send to server

                    //Prints server response to client
                    if (!message.equalsIgnoreCase("/caesarcipher")) {
                        String currentMessage = usrInput;
                        String encryptedMessage = caesarCipher.encrypt(currentMessage, serverKey);
                        output.println(encryptedMessage);
                        System.out.println("echo: " + message);
                    }
                }
                break;
            }
        }

        switch(usrInput) {
//          case "echo: Enter Website URL:":
//          case "iplookup terminating...":
//          case "Would you like to play the number game (Y/N)?":
//          case "You have guessed correctly! Game ending!":
//          case "echo: Enter a message to encrypt: ":
//              output.flush();

            case "echo: /quit":
            case "echo: /disconnect":
            case "echo: /killserver":
                output.close();
                input.close();
                stdIn.close();
                link.close();
                break;
        }
        //Flushes output for number game
        if(isNumeric(usrInput)){
            output.flush();
        }
    }
    //Checks string for numerical values and returns true if all numeric, false if other characters are present

    public static boolean isNumeric(String str) {
        for (char c : str.toCharArray()){
            if(!Character.isDigit(c)) return false;
        }
        return true;
    }
}

【问题讨论】:

    标签: java sockets networking echo-server


    【解决方案1】:

    坦率地说,要通读的东西太多了,如果你能更具体地描述你的代码的某些部分会更好,会有更多的人愿意帮助你。尽管如此,这里还是对您的代码有一些建议,希望对您有所帮助。


    对于您的第一个问题“...直到客户端的下一条消息...我才收到回显...”

    EchoClient 的变化:

        // ...
    
        CaesarCipher caesarCipher = new CaesarCipher();
        String serverKeyMessage = message;
    
        /* --- Delete 1 line : */
        // int serverKey = Integer.parseInt(serverKeyMessage.replaceAll("[^0-9]", ""));
    
        /* +++ Add 5 lines : */
        int serverKey;
        java.util.regex.Matcher m = Pattern.compile(".*([0-9]+).*").matcher(serverKeyMessage);
        if (m.matches()) serverKey = Integer.parseInt(m.group(1));
        else serverKey = 0;
        System.out.println(serverKeyMessage);
    
        // ...
    
    

    对于您的第二个问题“...直到 2 个后续...”

    EchoServer 的变化:

        // ...
    
        CaesarCipher caesarCipher = new CaesarCipher();
        //  currentMessage = input.readLine();   // delete this line
        currentMessage = inputLine;   // add this line
        String decryptedMessage = caesarCipher.decrypt(currentMessage, randomKey);
        
        // ...
    

    【讨论】:

    • 感谢@absuu,感谢您的建议,我现在将尝试您的代码建议。我是堆栈溢出和一般编码社区的新手,所以我仍在学习如何提出正确的问题。
    • 我测试了您的更改 - 我不敢相信我错过了那个输入问题。我尝试了你的正则表达式模式,它最终破坏了服务器端的解密方法,但你的更正帮助我解决了这个问题。谢谢@absuu!
    • @Yames 不客气!如果此答案或任何其他答案解决了您的问题,请点击复选标记考虑accepting it。这向更广泛的社区表明您找到了解决方案,并为回答者和您自己提供了一些声誉。无论如何,没有义务这样做。
    • 我试图给你投票但不能因为我是农民,但我给了你一个复选标记好先生!感谢您的帮助以及有关如何使用 stackoverflow 的建议。感谢您的时间和耐心。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-06
    相关资源
    最近更新 更多