C # потоковые сокеты, как разделять сообщения? - PullRequest
2 голосов
/ 15 октября 2008

Вроде длинный титул, но в любом случае ...

Я смотрел на эти примеры, особенно на части по написанию и чтению размера сообщения в байтовые потоки
http://doc.trolltech.com/4.4/network-fortuneclient-client-cpp.html
http://doc.trolltech.com/4.4/network-fortuneserver-server-cpp.html

Но я не могу понять это в C #.

StreamWriter writer = new StreamWriter(tcpClient.GetStream());
writer.Write(data.Length + data);

Это не очень хорошо работает. Может ли кто-нибудь подтолкнуть меня в правильном направлении?

Ответы [ 6 ]

2 голосов
/ 15 октября 2008

Как правило, вы бы отправили длину в первую очередь. Оба конца должны согласовать, как выглядит длина - например, вы можете использовать фиксированный 4-байтовый префикс длины в двоичном виде:

  byte[] data = ...
  int len = data.Length;
  byte[] prefix = Bitconverter.GetBytes(len);
  stream.Write(prefix, 0, prefix.Length); // fixed 4 bytes
  stream.Write(data, 0, data.Length);

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

Если вы не хотите, чтобы накладные расходы всегда отправляли 4 байта, тогда возможны некоторые более интересные кодировки - например, использование msb в качестве блока продолжения.

Для информации, protobuf-net - это двоичный сериализатор, разработанный на основе формата сообщений Google «буфер буферов». Он обрабатывает множество деталей для вас и может быть интересен, если вы не хотите тратить много времени на написание кода сериализации. В проекте QuickStart есть примеры для сокетов, например здесь

1 голос
/ 15 октября 2008

Полагаю, это должно быть сделано так: (Я предполагаю, что ваши данные являются строкой)

Stream stream = tcpClient.GetStream();
Encoding encoding = Encoding.GetEncoding("encoding name");

byte[] bytes = encoding.getBytes(data);

stream.Write(BitConverter.GetBytes((short)bytes.Length),0,2); // hope data isn't longer that 64k
stream.Write(bytes,0,bytes.Length);
1 голос
/ 15 октября 2008

Вместо data.Length попробуйте:

writer.Write(chr(data.Length) + data);

Это будет префикс каждого блока данных одним байтом, указывающим его длину (до 255 байтов). Как вы и просили, это только толчок. :)

Обновление: я только что вспомнил, что C # - это все Unicode и все такое, поэтому chr (), вероятно, дает вам более одного байта. Отрегулируйте, чтобы соответствовать.

0 голосов
/ 03 марта 2009

Использовать WriteLine вместо Write, ReadLine вместо Read ...

Если вы говорите, отправляя чисто текстовые сообщения, добавьте символ новой строки в конце ваших сообщений. Затем читайте байты, пока не встретите этот символ новой строки, и преобразуйте байты в строку. Для вашего удобства любые System.IO.StreamReader и System.IO.StreamReader реализуют это поведение в одном методе (WriterLine или ReadLine) writer.WriteLine («Строка для отправки»); string lineSent = reader.ReadLine ();

0 голосов
/ 15 октября 2008

Вы также можете, если вы хотите сохранить его текст, указать конкретный максимальный размер и дополнить число через строку. Формат. (Скажем, например, что разрешено использовать только 4 символа в длину) Это позволяет избежать проблем с числами в полезном потоке данных и упрощает декодирование.

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

0 голосов
/ 15 октября 2008

Когда вы говорите: «Это не очень хорошо работает», мне было бы интересно узнать, что именно не работает. Являются ли они .NET-приложениями на обоих концах сокета? Если это так, игнорируйте этот ответ. Если нет, то может ли проблема быть в порядке байтов целого числа? Немного по порядку байтов против большого Эта тема здесь обсуждает это:

http://bytes.com/forum/thread225649.html

http://books.google.com/books?id=2zT5b2BS1OUC&pg=PA64&lpg=PA64&dq=c%23+sockets+integers+byte+ordering&source=web&ots=_ISzZZ6HHT&sig=tUHdNT0NGv0uxusmHG9YjFw6j9k&hl=en&sa=X&oi=book_result&resnum=2&ct=result

Другая проблема, если оба конца не являются .NET, может заключаться в том, что другой конец ожидает строки ANSI, когда вы отправляете Unicode.

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