Java Socket Server — клиент; Застрял на стороне сервера

#java #sockets

#java #сокеты

Вопрос:

Это первый раз, когда я не могу найти проблему / ошибку в своем коде, поэтому теперь я спрашиваю stackoverflow xD

В настоящее время я изучаю, как написать простую серверно-клиентскую сеть, чтобы понять, как работают сокеты и серверные сокеты в Java. Поэтому я написал «программу», состоящую из класса сервера, клиента и обработчика. Класс обработчика отвечает за получение сообщений клиента и отправку ответа. Отправка с сервера на клиент работает отлично, клиент получает сообщение. Однако, когда Клиент отправляет сообщение на сервер, он ничего не получает. BufferedReader, который я использую, застрял в readLine() запросе.

 //This is the broken down version of what is happening in my Handler class
ServerSocket server = new ServerSocket(port); //These two lines of code actually happen in the Server class
Socket client = server.accept();              //but to simplify it I put them here
//Setting up the IO
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
//The Handler is waiting for the Reader to be ready and then prints the input
//Additionally, it sends a confirmation to the client
while(true) {
    String input;
    if(in.ready()){
        if ((input = in.readLine()) != null) {
            System.out.println(input);
            out.println("Message Received");
            if(input=="close") break;
        }
    }
}

//Expected output: "Message Received"
//Actual ouput: none, it gets stuck at in.ready() or in.readLine()
  

Когда я отправляю сообщение от клиента, оно должно просто распечатать сообщение и отправить подтверждение клиенту, но вместо этого оно либо никогда не проходит мимо if(in.ready()){...} части, либо застревает, if((input=in.readLine())!=null){...} если я удаляю первый оператор if. Я использовал IntelliJ для его отладки, и InputStream не содержит никакого сообщения или возврата каретки, который ожидается readLine() . Я нахожу это действительно странным, поскольку отправляющая и принимающая части как сервера, так и клиентского класса (в основном) одинаковы.

Единственное, что я мог придумать, что могло бы быть причиной этой проблемы, это то, что у клиента каким-то образом возникли проблемы с отправкой сообщения.

 //This is the broken down version of what is happening in my Client class
Socket client = new Socket();
client.connect(new InetSocketAddress("localhost",port));
//Setting up the IO
Scanner scanner = new Scanner(System.in); //I am using a Scanner for the message inputs
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
String input;
System.out.println("Enter the first Message: ");
while ((input = scanner.nextLine()) != null) {
    String inServer;
    System.out.println(input); //The input is correct
    out.println(input); //I am suspecting it has something to do with this line or the PrintWriter
    //This part works perfectly fine here while it does not in the Handler class
    if (in.ready()) {
        if ((inServer = in.readLine()) != null) {
            System.out.println(inServer);
        }
    }
    System.out.println("Enter next Message: ");
}
Expected output: inServer
Actual output: inServer
  

Как вы можете видеть, общая настройка этой части такая же, как и в классе обработчика, но, похоже, что-то идет не так при отправке на сервер. Я не знаю, сервер ли это (я так не думаю, потому что тот же код для получения сообщений отлично работает в классе Client) или Клиент, где в этом случае это должно быть проблемой с PrintWriter или что-то в этом роде.

Я уже рассматривал другие / похожие вопросы здесь, в stackoverflow, но не нашел ничего, что решило бы мою проблему. Полный код для классов, если кто-то хочет воспроизвести все в деталях: (Ссылки на Pastebin)

Класс сервера

Класс клиента

Класс обработчика

Комментарии:

1. Возможно, вы могли бы вызвать. flush() после печати?

2. Я установил значение автозапуска true при создании экземпляра PrintWriter, поэтому у меня это уже реализовано

3. in.ready() здесь нет ничего полезного, это просто трата процессорного времени в замкнутом цикле. Просто переместите код внутри оператора in.ready() if, чтобы он находился за пределами этого оператора, и удалите if .

4. Ваш код работает для меня. Когда клиент отправляет сообщение, например, «Hello World», сервер печатает строку [Server] received Message: Hello World

5. Вы внесли какие-либо изменения в код или просто скопировали классы из pastebin?

Ответ №1:

Ну, кажется, на вопрос был дан ответ… Похоже, это как-то связано с проектом IntelliJ, в котором был код. Мне пришлось перенести его в новый проект, и теперь он работает. Теперь проблема решена, и если кто-то захочет использовать этот код в качестве основы для серверно-клиентской системы, я оставлю ссылки на pastebin работающими.

Ответ №2:

Я предлагаю вам использовать метод read() классов, которые реализуют Reader (BufferedReader является одним из них). Синтаксис будет таким :

 String data = "";
int i;
while ((i = in.read()) != -1){
    data  = (char)i;
}
  

Этот способ намного надежнее и не имеет проблемы с возвратом каретки.