2012-05-29 5 views
0

Я пытаюсь реализовать сервер, и он делает что-то вроде этого, когда он получает сообщение:Как сервер может знать, когда сообщение, которое оно получает, происходит на самом деле?

try{ 
     ObjectInputStream is = new ObjectInputStream(clientSocket.getInputStream()); 
     String message = (String)is.readObject(); 
     ActivateCommand(message,clientSocket); 
     is.close(); 
    } 

и ActivateCommand:

private void ActivateEwolfCommand(String msg, Socket clientSocket) throws IOException 
{ 
    ObjectOutputStream os = new ObjectOutputStream(clientSocket.getOutputStream()); 
    Gson gsonObject = new Gson(); 
    . 
    //code which makes a Json string 
    . 
    os.writeObject(json); 
os.close(); 
} 

теперь, когда я тестировал его с отправкой сообщения к локальному хозяину с тестом junit он работал. Но когда вы попытались подключиться к серверу с помощью клиента C#, клиент подключился, но сервер выбрал исключение EOF при достижении точки clientSocket.getInputStream(). Я предполагаю, что это происходит потому, что сервер не знал, когда сообщение должно закончиться, но я не знаю, действительно ли это так, и если да, то как я могу его исправить?

+0

Как программист, вы можете передавать данные с помощью уникальной информации в конце. В точке получения укажите оператор if, проверяющий, попал ли код в конечные бит или нет! если он делает, то выйдите из цикла – doNotCheckMyBlog

+0

, но, как вы можете видеть, я просто создаю String msg = (String) is.readObject(), и я получаю сообщение в строке var ... как я могу сказать, что он останавливается, когда это видит какой-то особый характер или что-то еще? –

+0

Если вы хотите реализовать сервер Netty может оказаться полезным: http://netty.io –

ответ

0

Когда данных на InputStream нет, read() - это в основном то, что вызывает EOF. Сколько данных доступно клиенту - данные, которые он записывает на Socket's OutputStream со своей стороны, отображаются как таковые на InputStream сокета на стороне сервера. Вы можете позвонить InputStream.available(), чтобы получить оценку количества байтов, которое может быть еще read().

Однако ваш код пытается прочитать объект с использованием ObjectInputStream - этот класс имеет свой собственный протокол для чтения сериализованного потока байтов и преобразования его в объект - если он не находит байты для выполнения задачи, это может вызвать исключение EOF. Если ваш клиент находится в C# - формат байтов, который записывает для сериализованного объекта, определенно не будет таким же, как ожидалось, ObjectInputStream на стороне сервера.

+0

, значит ли это, что InputStream.available() не будет работать здесь? –

+0

'InputStream.available()' будет работать только так, как он сообщает вам, сколько сырых байтов вы можете прочитать с помощью ObjectInputStream - это работает нормально, но этого недостаточно для полного чтения объекта из - из-за несоответствия формата байта между сериализацией C# и десериализацией java. Вам нужно рассмотреть возможность использования некоторой структуры более высокого уровня, которая может обрабатывать взаимодействие данных между C# и java, или использовать сериализацию XML-кода. – Bhaskar

0

Вот почему это плохая идея создать собственный клиент-серверный протокол с потоками сокетов и объектов. Многие люди потратили много лет приносит вам, о, хорошо:

  • SOAP
  • REST
  • RMI
  • Hessian
  • CORBA
  • Бережливость

и множество другие протоколы. Разумеется, один из них, если не 5 или 6, достаточно хорош для решения вашей проблемы, включая все вопросы кадрирования.

0

Если вы хотите отправить строки по сокету, то ObjectInputStream или ObjectOutputStream не является правильной реализацией потока. Эти потоковые реализации используют сериализацию объектов Java. Даже если вы сериализуете String экземпляров, результирующие байты не совпадают с простой строкой для преобразования байтов с соответствующей кодировкой символов.

И приложение C# вообще не понимает сериализацию Java.

Рассмотрите возможность использования строки PrintWriter для записи строк в поток и BufferedReader для чтения.

PrintWriter writer = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream(), "UTF-8")); 
writer.println(...); 


BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), "UTF-8")); 
String line = reader.readLine(); 

Затем вы можете читать и писать строки по строкам. Это только отправная точка. Если вы хотите реализовать свой собственный протокол, вы должны обратить внимание на несколько пунктов.В качестве примера вы можете прочитать спецификации для некоторых протоколов TCP, таких как POP3, FTP или HTTP 1.0.

+0

, чтобы быть уверенным ... Я видел несколько примеров использования BufferedReader при чтении файла, и это было примерно так: try { BufferedReader in = new BufferedReader (новый FileReader ("infilename")); String str; while ((str = in.readLine())! = Null) { process (str); } in.close(); } catch (IOException e) { } Я предполагаю, что эта строка читает полную строку из файла до символа \ n каждый раз? что в случае сервера я могу использовать буферизованный читатель без цикла while, только если im assunming кто-то не передает мне полный файл? –

+0

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