Tcp / Ip Socket соединения в .NET - PullRequest
4 голосов
/ 03 октября 2008

Для моего текущего проекта мне нужно запросить данные XML через соединение через сокет tcp / ip. Для этого я использую класс TcpClient:

Dim client As New TcpClient()
client.Connect(server, port)

Dim stream As NetworkStream = client.GetStream()
stream.Write(request)
stream.Read(buffer, 0, buffer.length)

// Output buffer and return results...

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

Как лучше всего решить эту проблему? Первоначально я пытался зацикливаться, пока у меня не было действительного XML-документа, но я обнаружил, что между stream.Read вызовами базовый поток иногда отключается, и я пропускаю последнюю часть данных.

Ответы [ 4 ]

3 голосов
/ 03 октября 2008

Вы создаете цикл для чтения.

Stream.Read возвращает int для байтов, которые он прочитал, или 0, если достигнут конец потока.

Итак, это как:

int bytes_read = 0;
while (bytes_read < buffer.Length)
   bytes_read += stream.Read(buffer, bytes_read, buffer.length - bytes_read);

РЕДАКТИРОВАТЬ: теперь вопрос в том, как вы определяете размер буфера. Если ваш сервер сначала отправляет размер, это нормально, вы можете использовать приведенный выше фрагмент. Но если вам нужно читать до тех пор, пока сервер не закроет соединение, вам придется использовать try / catch (что хорошо, даже если вы знаете размер) и использовать bytes_read, чтобы определить, что вы получили.

int bytes_read = 0;
try
{
   int i = 0;
   while ( 0 < (i = stream.Read(buffer, bytes_read, buffer.Length - bytes_read) )
      bytes_read += i;
}
catch  (Exception e)
{
//recover
}
finally
{
if (stream != null)
   stream.Close();
}
2 голосов
/ 03 октября 2008

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

0 голосов
/ 04 мая 2009

Я настоятельно советую вам попробовать WCF для таких задач. Это дает вам, после не столь крутой кривой обучения, много преимуществ по сравнению с необработанными коммуникациями сокетов. Для поставленной задачи, я согласен с предыдущими ответами, вы должны использовать цикл и динамически распределять память по мере необходимости.

0 голосов
/ 12 февраля 2009

Это возможный способ сделать это и получить в «ответе» строку ответа. Если вам нужен байтовый массив, просто сохраните ms.ToArray ().

string response;

TcpClient client = new TcpClient();
client.Connect(server, port);
using (NetworkStream ns = c.GetStream())
using (MemoryStream ms = new MemoryStream())
{
    ns.Write(request);

    byte[] buffer = new byte[512];
    int bytes = 0;

    while(ns.DataAvailable)
    {
        bytes = ns.Read(buffer,0, buffer.Length);
        ms.Write(buffer, 0, bytes);
    }

    response = Encoding.ASCII.GetString(ms.ToArray());
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...