#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")
под myelse if
и получил его прямо на стороне сервера.
Ответ №1:
Попробуйте установить автозапуск в потоке печати при его создании … одно целое число не будет отправлено до тех пор, пока новая строка или буфер не будут заполнены.
autoFlush
— Логическое значение; если true, выходной буфер будет очищаться всякий раз, когда записывается массив байтов, вызывается один из методов println или записывается символ новой строки или байт (‘n’)
Также полезно:
- Используйте обмен сообщениями на основе строк, т. Е. Второй тип сообщения может быть
"pick:4"
(проверить сst.startsWith("pick")
помощью), а затем проанализировать целое число. С вашим кодом вы можете легко потерять состояние. (Однострочные сообщения являются «псевдоатомными»). - Не создавайте
DataInputStreams
в каждом методе прослушивателя, сделайте их объектными переменными (то же самое для потоков печати …). Нет необходимости (повторно) создавать объекты при каждом нажатии.
Комментарии:
1. Спасибо за ваш ответ, человек. Я прочитаю документацию, протестирую ваш метод и одобрю ваш ответ. Я не знал, что я не могу отправить одно целое число через сокет. Большое спасибо за это.
2. Ну, конечно, вы МОЖЕТЕ, но настройки по умолчанию в библиотеках не позволят вам этого сделать. Особенно с учетом накладных расходов на сетевой трафик из-за отправки только 32 бит полезной нагрузки, 3-полосных рукопожатий и всего такого 😉
3. итак, вы должны сообщить ему, что ХОТИТЕ сделать именно это (через
autoFlush
). Но опять же, я бы предложил объединить команду с целым числом и отправить ее в одной строке (т. Е. »pick:4
«, »pick-4
» или даже »pick4
«).