Сокеты Java 21
позволяют использовать несколько соединений
с использованием ObjectInputStream и ObjectOutputStream создают EOF при втором запросе
У меня есть клиентская сторона, мостовой сервер (посредник) и сервер инвентаря.
Клиент – это конечные пользователи.
Сервер представляет собой систему авторизации и своего рода шлюз к Серверу инвентаризации
Диаграмма последовательности следующая:
Теперь о проблеме:
Запуск BridgeServer
Запуск UserClient
и проверяем, установлено ли соединение.
Отправка любого типа запроса
(объекта) из опций, представленных в терминале.
во время своих прогонов я отправил запрос AuthenticationRequest.
java.io.EOFException
at java.base/java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2933)
at java.base/java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:3428)
at java.base/java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:985)
at java.base/java.io.ObjectInputStream.(ObjectInputStream.java:416)
at com.pe.distributed.system.bridge.BridgeServer.run(BridgeSide.java:44)
at com.pe.distributed.system.bridge.BridgeMain.main(BridgeMain.java:5)
Сокеты Java 21 позволяют использовать несколько соединений с использованием ObjectInputStream и ObjectOutputStream создают EOF при втором запросе У меня есть клиентская сторона, мостовой сервер (посредник) и сервер инвентаря.
[list] [*]Клиент – это конечные пользователи.
[*]Сервер представляет собой систему авторизации и своего рода шлюз к Серверу инвентаризации
[/list] Диаграмма последовательности следующая:
[img]https://i.sstatic.net/MBPIWPFp.png[/img]
Теперь о проблеме: [list] [*]Запуск BridgeServer [*]Запуск UserClient и проверяем, установлено ли соединение. [*]Отправка любого типа запроса (объекта) из опций, представленных в терминале.
во время своих прогонов я отправил запрос AuthenticationRequest. [*]Запрос AuthenticationRequest обрабатывается правильно. [*] Повторно отправьте AuthenticationRequest или [b]любой[/b] запрос. [*][b][code]EOFException[/code][/b] генерируется BridgeServer [/list] [code]java.io.EOFException at java.base/java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2933) at java.base/java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:3428) at java.base/java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:985) at java.base/java.io.ObjectInputStream.(ObjectInputStream.java:416) at com.pe.distributed.system.bridge.BridgeServer.run(BridgeSide.java:44) at com.pe.distributed.system.bridge.BridgeMain.main(BridgeMain.java:5) [/code] Для контекста и воспроизводимости: [b]UseClient[/b] [code] import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.net.Socket; import java.util.Map; import java.util.Scanner; import java.util.logging.Level; import java.util.logging.Logger;
public record AuthenticationRequest(String username, String password) implements Serializable { }
public record InventoryQuery() implements Serializable { }
public record ItemOrder(String itemCode, int quantity) implements Serializable { }
public class UserClient { private static final Logger logger = Logger.getLogger(UserClient.class.getName()); private static final String EXCEPTION_OCCURRED = "Exception occurred";
private UserClient() { }
@SuppressWarnings("java:S2189") public static void run() { Scanner scanner = new Scanner(System.in); while (true) { try (Socket bridgeSocket = new Socket("127.0.0.1", 5550)) { logger.log(Level.INFO, "Connected successfully to bridge server");
while (true) { displayMainMenu(); int choice = scanner.nextInt(); scanner.nextLine();
// Handle user choice switch (choice) { case 1: authenticate(scanner, bridgeSocket); break; case 2: checkInventory(bridgeSocket); break; case 3: placeOrder(scanner, bridgeSocket); break; default: logger.log(Level.WARNING, "Invalid choice. Please enter a valid option."); } } } catch (IOException | ClassNotFoundException e) { logger.log(Level.SEVERE, EXCEPTION_OCCURRED, e); } finally { scanner.close(); } } }
@SuppressWarnings("java:S106") private static void displayMainMenu() { System.out.println("What would you like to do:"); System.out.println("1. Authenticate"); System.out.println("2. Check Inventory"); System.out.println("3. Place an Order"); System.out.print("Enter your choice: "); }
ObjectOutputStream bridgeIn = new ObjectOutputStream(socket.getOutputStream()); bridgeIn.writeObject(itemOrder); bridgeIn.flush();
ObjectInputStream bridgeOut = new ObjectInputStream(socket.getInputStream()); Object response = bridgeOut.readObject(); logger.log(Level.FINE, "Received response from bridge: {0}", response); }
@SuppressWarnings("java:S106") private static Map.Entry getUserOrderInput(Scanner scanner) { System.out.println("Place your order!\n");
String itemCode; int desiredQuantity;
// Input validation loop for item code do { System.out.print("Item-code: "); itemCode = scanner.nextLine(); } while (itemCode == null || itemCode.isEmpty());
// Input validation loop for quantity do { System.out.print("Quantity: "); while (!scanner.hasNextInt()) { System.out.println("Invalid input. Please enter a valid number."); scanner.next(); // Consume the invalid input } desiredQuantity = scanner.nextInt(); scanner.nextLine(); // Consume newline character } while (desiredQuantity как и ожидалось.
[*]Другие говорят, что объект(ы) ObjectInputStream и фактический InputStream Socket могут быть [b]не синхронизированы[/b]. [/list] Возможно, я неправильно понял возможности сокетов, но [list] [*]Я хочу, чтобы мой сервер поддерживал соединение до тех пор, пока клиент не закроет его.
[*]И чтобы все запросы обрабатывались корректно. [/list] И, конечно же, отсутствие EOFException ошибки. Будем рады отзывам!
Я только что нашел комментарий в этом ответе, в котором говорится, что использование iostream::eof в условии цикла «почти наверняка неправильно». Обычно я использую что-то вроде while(cin>>n), которое, я думаю, неявно проверяет наличие EOF.
Это программа, в которой я пытаюсь напечатать сериализуемый объект, используя readObject() ObjectInputStream, но в конце файла программа показывает ошибку, например
java.io.EOFException
at...
ObjectInputStream будет инициализироваться нормально только при создании ObjectInputStream на стороне клиента и ObjectOutputStream на стороне сервера, но при последующем создании ObjectInputStream на стороне сервера выполнение просто останавливается...