Как я могу отправить строку и целое число через сокет?

#java #sockets

#java #сокеты

Вопрос:

У меня есть 2 кнопки в моем клиенте с прослушивателем кнопок каждая.

В моем первом прослушивателе кнопок я отправляю строку через сокет и получаю обратно массив целых чисел после его преобразования. Никаких проблем нет. Вот мой код.

 public void rollDice() {

    try {
        DataOutputStream sout1 = new DataOutputStream(socket.getOutputStream());
        String line = "dice";
        PrintStream out1 = new PrintStream(sout1);
        out1.println(line);
    } catch (UnknownHostException e1) {
        e1.printStackTrace();
    } catch (IOException e1) {
        e1.printStackTrace();
    }

}
  

Со вторым слушателем я хочу сначала отправить строку, чтобы перевести сервер в правильное состояние, а после я хочу отправить целое число для продолжения процесса. Вот мой код, но, похоже, он не работает. Сервер печатает случайное число, даже если я отправляю «2».

 public void sendDice() {

    try {
        DataOutputStream sout2 = new DataOutputStream(socket.getOutputStream());
        String line = "pick";
        PrintStream out2 = new PrintStream(sout2);
        out2.println(line);

        out2.write(diceListLength);
    } catch (UnknownHostException e1) {
        e1.printStackTrace();
    } catch (IOException e1) {
        e1.printStackTrace();
    }
}
  

Вот сторона сервера.

 public void run() {

        boolean running = true;

        try {

            // Create streams for reading / writing lines of text to the socket
            DataInputStream input = new DataInputStream(s.getInputStream());
            DataInputStream inputInt = new DataInputStream(s.getInputStream());

            ObjectOutputStream output = new ObjectOutputStream(s.getOutputStream());

            // Print a message:
            System.out.println("nClient from: "   s.getInetAddress()   " port "   s.getPort());

            while(running) {
                String st = input.readLine();

                if (st.equals("dice")) {
                    for (int i = 0; i < diceRolled.length - number; i  ) {
                        diceRolled[i] = (int) ( 1   Math.random() * 6);
                        System.out.print(diceRolled[i]   " ");
                    }
                    output.writeObject(diceRolled);
                    output.reset();
                } else if (st.equals("pick")) {
                    number = inputInt.readInt();
                    System.out.print(number);

                }
            } 
        } catch (IOException e) {
            System.out.println("Error: "   e.getMessage());
         // Always be sure to close the socket
        } finally {
            try {
                if (s != null) {
                    System.out.println(s.getLocalSocketAddress()   " closed.");
                    s.close();
                }                   
            } catch (Exception e) {
                System.out.println("Error: "   e.getMessage());
            }
        }
    }
  

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

1. Где находится SocketInputStream на стороне сервера?

2. Я использую @Nullpointer DataInputStream , но я не вставил весь код. Обновлено.

3. Попробуйте напечатать значение st .. это правильно?

4. Я предполагаю, что он не знает, где их разделить во входном потоке.

5. @Nullpointer да, я это проверял. Я использовал a System.out.println("it works") под my else if и получил его прямо на стороне сервера.

Ответ №1:

Попробуйте установить автозапуск в потоке печати при его создании … одно целое число не будет отправлено до тех пор, пока новая строка или буфер не будут заполнены.

Из документации java

autoFlush — Логическое значение; если true, выходной буфер будет очищаться всякий раз, когда записывается массив байтов, вызывается один из методов println или записывается символ новой строки или байт (‘n’)

Также полезно:

  1. Используйте обмен сообщениями на основе строк, т. Е. Второй тип сообщения может быть "pick:4" (проверить с st.startsWith("pick") помощью), а затем проанализировать целое число. С вашим кодом вы можете легко потерять состояние. (Однострочные сообщения являются «псевдоатомными»).
  2. Не создавайте DataInputStreams в каждом методе прослушивателя, сделайте их объектными переменными (то же самое для потоков печати …). Нет необходимости (повторно) создавать объекты при каждом нажатии.

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

1. Спасибо за ваш ответ, человек. Я прочитаю документацию, протестирую ваш метод и одобрю ваш ответ. Я не знал, что я не могу отправить одно целое число через сокет. Большое спасибо за это.

2. Ну, конечно, вы МОЖЕТЕ, но настройки по умолчанию в библиотеках не позволят вам этого сделать. Особенно с учетом накладных расходов на сетевой трафик из-за отправки только 32 бит полезной нагрузки, 3-полосных рукопожатий и всего такого 😉

3. итак, вы должны сообщить ему, что ХОТИТЕ сделать именно это (через autoFlush ). Но опять же, я бы предложил объединить команду с целым числом и отправить ее в одной строке (т. Е. » pick:4 «, » pick-4 » или даже » pick4 «).