Я разрабатываю простое приложение Client-Server поверх сокета, но я не могу понять, почему клиент зависает, когда он читает объект. Сервер должен иметь возможность работать с несколькими клиентами.
Сохраняя это просто, мой Сервер выглядит так:
...
server_thread = new Thread(new Runnable() {
@Override
public void run() {
int p = 0;
ObjectInputStream in;
ObjectOutputStream out;
NetworkOffer message;
try (ServerSocket serverSocket = new ServerSocket(port)) {
// get connections
LinkedList<Socket> client_sockets = new LinkedList<>();
while (p++ < partecipants) client_sockets.add(serverSocket.accept());
// sending welcome object
for (Socket socket : client_sockets) {
out = new ObjectOutputStream(socket.getOutputStream());
message = new NetworkOffer();
out.writeObject(buyer_offer);
}
...
Мой клиент:
...
client_thread = new Thread(new Runnable() {
@Override
public void run() {
ObjectInputStream in;
NetworkOffer smessage;
try {
Socket ssocket = new Socket("localhost", port);
in = new ObjectInputStream(ssocket.getInputStream());
// waiting server message
------------->Object o = in.readObject();
smessage = (NetworkOffer)o;
System.out.println(smessage.toString());
...
EDIT: Чтобы сделать все более ясным, это протокол, который я хочу реализовать:
Сервер отправляет welcome
клиентам
Каждый клиент делает предложение
Accept/Reject
Клиент Object o = in.readObject();
даже если сервер уже отправил свое сообщение. Нет ошибки, ничего. Тема просто замораживается там, ожидая чего-то.
Что происходит?
Как я уже говорил, вы уверены, что сервер отправил данные клиенту - нет флеш-буфера, поэтому он все еще может кэшироваться. out.flush()
будет следить за тем, чтобы буфер был сброшен. Будет иметь смысл обрабатывать клиентов отдельно и отправлять им периодические сообщения, чтобы обновить их о статусе.
Полезно, чтобы код вашего сервера обрабатывал также отключение соединения/соединения клиента.
На стороне примечание:
message = new NetworkOffer();
out.writeObject(buyer_offer);
Ваш код, кажется, отправляет что-то еще, чего нет в вашем примере. Это верно?
Проблема заключается в том, что ServerSocket.accept()
- это блокирующий вызов, означающий, что сервер будет зависать, пока кто-то не подключится к нему. Когда кто-то подключится, сервер добавит этот новый сокет в client_sockets
. Если количество добавленных сокетов меньше participants
, оно снова вызовет accept()
и ждет другого соединения. Он будет вводить только ваш цикл for
если общее количество сокетов равно participants
. Вам нужно создать новый поток для обработки каждого входящего клиентского сокета и разрешить серверу немедленно вернуться к ServerSocket.accept()
. Взгляните на шаблон Reactor для хорошего примера того, как это реализовать.
Как выглядит ваш код:
client_sockets
и ждет предложений клиентов.Accept/Reject
сообщений.
accept()
является блокирующим вызовом. Что я не могу понять, так это: все клиенты подключаются: хорошо. Затем сервер отправляет первый «добро пожаловать»; на этом этапе один поток клиента не должен быть освобожден и продолжать? Вместо этого все клиенты заблокированы вin.readObject();
, Почему это происходит?