2013-05-31 3 views
0

Я пытаюсь исправить ошибку связи со связью Java, где сервер не знает длину входного сообщения. В текущей ситуации серверный тест, если ввод завершен с использованием метода inputStream.available();. Однако этот метод не возвращает правильный ответ всегда. и он вызывает чтение частичного ввода. Кажется, есть две разные возможности для решения этой проблемы.Сокетная связь с неизвестной длиной ввода

  1. Клиент должен отправить размер ввода.

  2. Клиент должен закрыть свой выходной поток после отправки, но это заставляет клиент не читать ответ, так как сокет также закрыт, когда выходной поток закрыт.

Есть ли какие-либо другие предложения, особенно с помощью пакетов nio?

спасибо.

ответ

1

Вы можете использовать

socket.shutdownOutput(); 

, чтобы закрыть выходной поток клиента. Это будет отображаться как закрытый поток ввода без закрытия сокета.

BTW: Вы не можете использовать socket.getOuputStream().close();, как я мог бы.

IMHO, отправляющий длину, является лучшим вариантом, так как это позволит вам отправлять несколько запросов с использованием одного и того же сокета.


Ниже приведен пример

public class SimpleServerMain { 
    public static void main(String... args) throws IOException, InterruptedException { 
     ServerSocket ss = new ServerSocket(54321); 
     Socket s = ss.accept(); 
     BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); 
     for (String line; (line = br.readLine()) != null;) 
      System.out.println("Got " + line); 

     PrintStream ps = new PrintStream(s.getOutputStream()); 
     for (String word : "Hello World Bye Bye!".split(" ")) { 
      ps.println(word); 
      Thread.sleep(1000); 
     } 
     s.close(); 
     ss.close(); 
    } 
} 

и

public class SimpleClientMain { 
    public static void main(String... args) throws IOException { 
     Socket s = new Socket("localhost", 54321); 
     InputStream inputStream = s.getInputStream(); 

     s.getOutputStream().write("Hello\n".getBytes()); 
     s.shutdownOutput(); 

     BufferedReader br = new BufferedReader(new InputStreamReader(inputStream)); 
     for (String line; (line = br.readLine()) != null;) 
      System.out.println("Got " + line); 
     System.out.println("Disconnected."); 
     s.close(); 
    } 
} 
+0

Благодарим за быстрый ответ, я попытался закрыть входной поток на стороне клиента, но это также вызывает закрытие соединения. Таким образом, после закрытия входного клиента клиент не может прочитать ответ, так как сокет закрыт. – cacert

+0

Закрытие выходного потока не обязательно должно закрывать соединение, но некоторые библиотеки могут это сделать. Если они это сделают, это ошибка ИМХО. Сокет не закрывается, пока один конец не закроет его. Если вы используете библиотеку, которая закрывает сокет без вашего ведома, я предлагаю вам использовать другую библиотеку. –

+0

Я использую стандартную java api IBM jdk. Я думаю, что это поведение по умолчанию. Но я попробую socket.shutdownInput(). здесь ссылка link.http: //stackoverflow.com/questions/3956163/does-closing-the-inputstream-of-a-socket-also-close-the-socket-connection – cacert

0

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

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

0

Есть, по крайней мере, два других метода, которые не упоминаются, вероятно, должны быть.

  1. Используйте специальный символ, обозначающий конец определенного входа. Если на входе нет новых линий, то выбор возможен \r\n.

  2. Используйте некоторую сериализацию - вы можете отправить данные как объект JSON или XML или так, тогда вы узнаете, когда данных больше нет.

1

available() не мера длины сообщения, так что нет никаких оснований для того, чтобы вернуть «правильный ответ», если ваше определение «правильный ответ» является "длина сообщения.

Если вы хотите, чтобы длина сообщения у вас была , отправьте. Или используйте строки или самоописательный протокол, например XML, сериализацию и т. Д.

Смежные вопросы