#java #sockets
#java #сокеты
Вопрос:
Краткие сведения
Я создаю простую одноранговую шахматную игру на Java. Хост успешно подключается, но соединитель не получает свое сообщение. Я использую PrintWriter
и BufferedReader
для отправки и получения сообщений. Я подозреваю, что PrintWriter
неправильно себя ведет, но я не уверен.
Предварительное исследование
Я искал «Клиент, не получающий сообщение сервера», но проблема, с которой все сталкивались, заключалась в том, что они не использовали println
со своим PrintWriter
. Я использую println
, поэтому ни один из них не применялся ко мне. Я также переместил поля ввода и вывода из метода в класс, что и было сказано в одном ответе, но это не решило проблему.
Некоторый код
Прослушивающий код
try (ServerSocket serverSocket = new ServerSocket(this.port)) {
// We need to connect with another computer
if (this.other == null || this.other.isClosed()) {
System.out.println("Looking for connection on port " serverSocket.getLocalPort());
this.in = null;
this.out = null;
// Listen for connectors
this.other = serverSocket.accept();
// Someone tried to connect, handle connection
System.out.println("Player connected");
this.in = new BufferedReader(new InputStreamReader(this.other.getInputStream()));
this.out = new PrintWriter(this.other.getOutputStream(), true);
// Autoflush is enabled! ^^^^
// This does not get to the client
this.sendMessage("connectHost");
}
// We are currently connected to another computer, no need to look for more
else {
String input = this.in.readLine();
System.out.println("Received '" input "'");
if (input != null) {
// Handle input
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
Отправка кода
if (this.out != null) {
// See, it is println, so I don't need to call out.flush()...
this.out.println(message);
System.out.println("Sent '" message "'");
}
Код команды подключения
try {
// The host picks up on this
this.other = new Socket(ip, port);
this.in = new BufferedReader(new InputStreamReader(this.other.getInputStream()));
this.out = new PrintWriter(this.other.getOutputStream(), true);
// Works
this.sendMessage("test");
} catch (IOException ioe) {
ioe.printStackTrace();
}
Проблема
Оно должно быть распечатано Received 'connectHost'
на соединителе, но этого не происходит. Вместо этого он блокирует, от in.readLine()
вызова без in
получения данных. Если я вставлю in.ready()
проверку, она всегда будет возвращаться false
.
Консоль соединителя
Looking for connection on port 57479
connect localhost 57478 // Command to connect to host
Sent 'test' // Successfully goes to the host
// Now it blocks. This is intended, but it should be saying "Received 'connectHost'" beforehand.
Консоль хоста
Looking for connection on port 57478
Player connected
Sent 'connectHost'
Received 'test' // Host gets it
// This also blocks, waiting for more messages, but that is intended.
Обновить:
Я просто попытался отправить сообщение непосредственно после подключения (см. Обновленный код), и хост его получает. Соединитель по-прежнему не получает сообщение от хоста.
Комментарии:
1. Где находится код, который печатает то, что вы обозначили как «консоль соединителя»?
2. Если вы отправляете (и получаете) как с сервера, так и с клиента, вам понадобятся отдельные потоки для каждого прослушивающего сокета
3. «Код подключения» не устанавливается this.in или this.out, это намеренно?
4. @Scary Wombat Запущено два экземпляра одного и того же кода.
5. @immibis Увидев ваш комментарий, я попробовал, но без разницы.
Ответ №1:
Это было очевидно…
serverSocket.accept()
Была блокировка, не позволяющая соединителю считывать входные данные. Итак, in.readLine()
проблема не в этом. Я сделал это так, чтобы пользователь должен был указать программе прослушивать соединения. Теперь это работает.
Новый код
Прослушивающий код
try (ServerSocket serverSocket = new ServerSocket(this.port)) {
if (this.listening amp;amp; (this.other == null || this.other.isClosed())) {
System.out.println("Looking for connection on port " serverSocket.getLocalPort());
this.in = null;
this.out = null;
this.other = serverSocket.accept();
this.in = new BufferedReader(new InputStreamReader(this.other.getInputStream()));
this.out = new PrintWriter(this.other.getOutputStream(), true);
} else if (this.in != null) {System.out.println("Looking for input");
String input = this.in.readLine();
System.out.println("Received '" input "'");
if (input != null) {
// Process input
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
Код отправки не изменился.
Код подключения
if (input.contains("connect")) {
String[] args = input.replaceAll("connect ", "").split(" ");
String ip = args[0];
int port = Integer.parseInt(args[1]);
try {
this.other = new Socket(ip, port);
this.in = new BufferedReader(new InputStreamReader(this.other.getInputStream()));
this.out = new PrintWriter(this.other.getOutputStream(), true);
this.sendMessage("connect");
} catch (IOException ioe) {
ioe.printStackTrace();
}
} else if (input.contains("listen")) {
this.listening = true;
}