C # чтение двоичных данных из сокета - PullRequest
3 голосов
/ 13 сентября 2010

Я работаю над приложением, которое читает и записывает двоичные данные из и в сокет.Итак, сначала я создаю сокет с TcpClient.Но я застрял на чтении данных из сокета.Есть ли примеры кода для чтения двоичных данных из сокета?

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

Спасибо

Ответы [ 4 ]

5 голосов
/ 13 сентября 2010

Документация TCPClient от Microsoft на самом деле очень полезна.

Как читать данные из TCPClient

Ключевая часть вПример Microsoft для чтения данных из сокета:

// Get the stream
NetworkStream stream = client.GetStream();
Byte[] data = new Byte[256];

// String to store the response ASCII representation.
String responseData = String.Empty;

// Read the first batch of the TcpServer response bytes.
int bytes = stream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);

Они используют метод GetStream класса TCPClient и читают все доступные данные (додо 256 байт) из потока.

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

Лучший способ справиться с этим ниже ...

Как сделатьВы знаете, получено ли сообщение?

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

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

Например, ваша спецификация сообщения может быть такой:

ДАННЫЕ привет друг
END

При поиске END следуютпри возврате каретки вы узнаете, что нашли конец сообщения.Аналогичным образом, маркер DATA в начале помогает вам определить, где начинается сообщение, и разделить данные сообщения.

Как лучше всего читать эти данные?

Все отправленные / полученные данные будут в двоичном формате, вам необходимо кодировать и декодировать данные.В этом примере они преобразуют двоичные данные в строку (и наоборот), используя встроенные методы кодирования ASCII GetString и GetBytes .

Рассмотрите возможность реализации известного протокола

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

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

1 голос
/ 13 сентября 2010

В этом случае я буду откладывать на MSDN. В частности, работа с TcpClients (поддержание соединения - что вы уже делаете), TcpListeners (прием соединений и начало связи), а также сериализация (преобразование данные в / из двоичного файла).

0 голосов
/ 13 сентября 2010

Первым шагом является вызов GetStream для экземпляра TcpClient, который дает вам ссылку на NetworkStream, с помощью которого вы отправляете и получаете двоичные данные. Вы можете заключить это в BinaryReader и BinaryWriter для отправки и получения примитивов .NET (например, Int32s, Strings и так далее) или использовать методы NetworkStream непосредственно для байтовых массивов. Вы найдете полезными члены NetworkStream.Read, NetworkStream.BeginRead и NetworkStream.DataAvailable; см. http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream_members.aspx для получения дополнительной информации.

0 голосов
/ 13 сентября 2010

Все данные, передаваемые через сокет, являются двоичными. Вам решать интерпретировать это как что-то еще, например как строку. Вы можете использовать подобные функции для отправки или получения данных. Вы можете вызывать их с помощью NetworkStream, который вы получаете от вашего NetworkStream stream = client.GetStream();. Обратите внимание, что эти функции сначала отправляют int с размером данных.

public void send(NetworkStream stream, byte[] buf) {
    stream.Write(BitConverter.GetBytes(buf.Length), 0, 4);
    stream.Write(buf, 0, buf.Length);
}

public byte[] receive(NetworkStream stream) {
    byte[] lengthBytes = new byte[4];
    int read = stream.Read(lengthBytes, 0, 4);
    // read contains the number of read bytes, so we can check it if we want
    int length = BitConverter.GetInt32(lengthBytes);
    byte[] buf = new byte[length];
    stream.Read(buf, 0, buf.length);
    return buf;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...