Проблемы написания протокола поверх сокетов в Java - PullRequest
1 голос
/ 03 августа 2010

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

По сути, это выглядит так:

while ((length = inStream.read(buffer)) != -1)
{
   dispatch(buffer, length);
}

Таким образом, метод отправки затем расшифровывает заголовки и делегирует метод в зависимости от того, что найдено в заголовке.Это выглядит примерно так:

byte[] clearText = decrypt(message,length);
if (cleartext == foo) sendFooToSocket();

Так что тогда sendFooToSocket () будет сидеть там и читать из instream или отправлять в outtream.Здесь я, кажется, сталкиваюсь с некоторыми проблемами: в клиенте я отправляю заголовок, затем сбрасываю, затем отправляю остальные данные, но кажется, что все идет как единое целое и не разделяется на заголовок, а затем данные.Также есть ли лучший способ принудительного использования метода sendFooToSocket?

public void sendFooToSocket()
{
  byte[] buffer = new byte[1024];
  int length = 0;
  while ((length = inStream.read(buffer) >0)
  {
    message = decrypt(buffer, length);
  }
}

Я бы предположил, что flush позволит мне выйти из этого метода, когда он закрывается, а затем открывает поток?

Итак, у меня есть 2 проблемы, похоже, что flush не разрушает мои сообщения, а flush, похоже, не позволяет выпадать из таких методов, как sendFooToSocket (), какие-либо предложения?

Для ясности, клиент просто делает это:

byte[] header = "MESG".getBytes();
cipher = encrypt(header);
outStream.write(cipher,0,cipher.length);
outStream.flush();
byte[] message = "Hi server".getBytes();
cipher = encrypt(message);
outStream.write(cipher,0,cipher.length);
outStream.flush();

Но это принимается сервером как 1 сообщение, даже если оно сбрасывалось после каждой записи.Отправка только заголовка работает, и мы застреваем в методе sendFooToSocket (), но если я отправляю данные после сброса, они приходят сразу.

Клиент использует OutputStream и InputStreams только из socket.get,Клиент также использует OutputStream и InputStream.Не уверены, имеет ли это значение?

Ответы [ 3 ]

3 голосов
/ 03 августа 2010

То, что вы, кажется, хотите, это "границы записи". С потоками вообще нет никаких неявных границ записи. Если вам нужна такая функциональность, вам нужно реализовать ее самостоятельно, буферизуя ввод и ища, скажем, новые строки, чтобы указать конец записи.

Посмотрите на BufferedInputStream.

1 голос
/ 03 августа 2010

Если вы на самом деле не хотите управления на уровне, который вы реализовали, вы можете рассмотреть потоки объектов (см. ObjectInputStream и ObjectOutputStream).Такие потоки позволят вам отправлять Java-объекты через сокеты и читать их на другом конце без необходимости иметь дело с заголовками и границами и т. Д. См. ObjectOutputStream для получения дополнительной информации, но это довольно много:

Отправитель: writeObject (objectX)

Получатель: myCopyOfObjectx = readObject ()

, и вы можете отправлять любые объекты, которые вам нравятся (если они являются сериализуемыми).

1 голос
/ 03 августа 2010

inStream.read () может не возвращаться на границе сообщения. Вы не можете предполагать, что он вернется на какой-либо конкретной границе (например, пустая строка, разделяющая заголовки и контент, если вы так делаете.) Вам придется вручную анализировать контент и игнорировать тот факт, что приходят из нескольких read () или, может быть, один read () содержит как заголовки, так и содержимое.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...