Mail.ruПочтаМой МирОдноклассникиВКонтактеИгрыЗнакомстваНовостиКалендарьОблакоЗаметкиВсе проекты

Java сетевое программирование

RostikP Знаток (407), открыт 2 недели назад
Добрый день. У меня такая проблема (скорее всего очень распространенная, но я не знаю как грамотно её сформулировать, чтобы самому найти ответ). Эта проблема меня преследует с сетевого программирования на С.

К делу, мне необходимо в цикле отправить большой кусок данных, а именно, тип String, в котором данные размещены примерно так "hello world\nyes\no\nno problem\n" и так далее.
Очень большая строка состоящая из символов пробела и новой строки.

Изначально я пробовал это все отправлять построчно, но после подумал к каждой строке на конец прибавлять \n и вот таким образом все за раз отправить но ничего не помогло.

Проблема в том, что клиент не может адекватно прочесть всю информацию. Он либо её не читает, либо читает не до конца (то есть не всю информацию), то либо читает всю эту информацию с дубликатами этой информации, то есть некоторые куски встречаются по 5-10 раз.

Я не понимаю, как правильно отправлять такие большие куски данных и правильно их обрабатывать, чтобы не было потерь или дублирующийся информации. Зачастую клиент оказывается в такой ситуации: он все прочел, но каким-то образом все равно оказался на строке, где необходимо читать ввод с сервера и это блокирующая операции, то есть программа клиента зависает. Я также пробовал на конец строки, отправляемой сервером, прибавлять "завершающее слово" типа "stop" или что-то такое, но это тоже не помогло, потому что клиент читает информацию неравномерно, он почему-то может за один раз прочесть половину всех строк, а не каждую по отдельности или вообще непонятно как прочесть.

Код сервера:

  private void serverCheckDatabase(String command) { 
if (command.equalsIgnoreCase("loaditem")) {
System.out.println("command:" + command);
String sendData = "";
for (English english : dataArrayList) {
sendData += english.toString();
sendData += "\n";
}
serverSendDataToClient(sendData);

serverSendDataToClient(".stop.");
}

}

*сервер правильно формирует пласт информации и по идее правильно ее отправляет*


Код клиента:

 public static String ListenForMessage() { 
StringBuilder serverMessageBuilder = new StringBuilder();
String line;

try {
if (socket.isConnected()) {

while ((line = bufferedReader.readLine()) != null) {
if (line.equalsIgnoreCase(".stop."))
break;
serverMessageBuilder.append(line).append("\n");
System.out.println(line);
}
}
} catch (IOException e) {
System.out.println("IOEXCEPTION");
throw new RuntimeException(e);
}

String serverMessage = serverMessageBuilder.toString();
System.out.println(serverMessage);

return serverMessage;
}
Дополнен 2 недели назад
Скрин работы сервера:Скрин работы клиента:Неравномерно прочел куски данных с дубликатами. Опять программа клиента зависла. Помогите пожалуйста с правильным обменном информацией в сетевом программировании в Джава.
Дополнен 2 недели назад
пожалуйста не отправляйте мне ваши промпты от нейросетей. Я и сам могу это сделать. Мне нужен ответ от человека, который разбирается и может поделиться опытом.
2 ответа
Дмитрий Феофилов Знаток (268) 2 недели назад
Проблема, с которой вы сталкиваетесь, вероятно, связана с тем, что вы используете `readLine()` для чтения данных на стороне клиента. `readLine()` читает строки до символа новой строки (`\n`), поэтому если в вашем сообщении содержатся строки без этого символа, `readLine()` будет ждать, пока он не встретит `\n`, что может привести к блокировке.

Вот несколько вариантов, как можно решить эту проблему:

1. **Используйте другой метод чтения данных на клиенте:** Вместо `readLine()`, который ждет символ новой строки, вы можете использовать `read()` или `read(byte[])`, чтобы читать данные порциями без ожидания символа новой строки. Это позволит вам прочитать данные до конца.

2. **Используйте фиксированную длину сообщения:** Если вы знаете фиксированную длину сообщения, которую вы отправляете с сервера, вы можете прочитать эту длину данных на клиенте и затем обработать данные соответственно.

3. **Используйте специальный разделитель:** Как вы уже пробовали, вы можете добавить специальный разделитель в конец каждого сообщения (например, вашего "stop") и читать данные до того момента, пока вы не встретите этот разделитель на стороне клиента.

Пример кода для чтения данных на стороне клиента с использованием `read()`:

```java
public static String listenForMessage() {
StringBuilder serverMessageBuilder = new StringBuilder();
char[] buffer = new char[1024]; // Размер буфера для чтения данных

try {
if (socket.isConnected()) {
InputStreamReader inputStreamReader = new InputStreamReader(socket.getInputStream());
int bytesRead;

// Читаем данные порциями в буфер
while ((bytesRead = inputStreamReader.read (buffer)) != -1) {
// Добавляем прочитанные данные к общему сообщению
serverMessageBuilder.append(buffer, 0, bytesRead);
}
}
} catch (IOException e) {
System.out.println("IOEXCEPTION");
throw new RuntimeException(e);
}

String serverMessage = serverMessageBuilder.toString();
System.out.println(serverMessage);

return serverMessage;
}
```

Этот код будет читать данные порциями в буфер и добавлять их к общему сообщению, пока данные не будут полностью прочитаны.
RostikPЗнаток (407) 2 недели назад
мне не нужны ответы нейросети.
RostikP, они невменяемые
Супермаркет Знаток (276) 2 недели назад
Чтобы правильно отправлять большие куски данных и избежать дублирования информации, попробуйте использовать следующие подходы:
1. Разбивайте данные на более мелкие фрагменты и отправляйте их по частям. Это поможет клиенту получать информацию равномерно и без дубликатов.
2. Добавьте «завершающие слова» на концах строк, отправляемых сервером. Например, используйте «\n» для разделения строк или «.stop.» для обозначения конца передачи данных.
3. Используйте протокол сжатия данных, такой как GZIP или LZ4, чтобы уменьшить размер передаваемых данных и ускорить процесс отправки.
4. Обеспечьте надёжное соединение между сервером и клиентом, используя SSL/TLS для шифрования и аутентификации трафика.
5. Регулярно проверяйте состояние соединения и обрабатывайте ошибки, возникающие при передаче данных.
6. Используйте асинхронную передачу данных, чтобы улучшить производительность и снизить нагрузку на сервер.
7. Рассмотрите возможность использования фреймворков или библиотек для сетевого программирования, таких как Netty, Spring Integration или Apache Camel, которые могут упростить обработку больших объёмов данных и обеспечить лучшую производительность.
Похожие вопросы