C #: невозможно получить большие данные на TCP-сервере - PullRequest
2 голосов
/ 18 октября 2010

Я создал TCP-сервер.Я сталкиваюсь с одной проблемой.мой TCP-сервер не получает данные размером более 30000 байт.

вот код для получения данных

MAX_TCP_DATA = 64000

private void Process()
        {
            if (client.Connected == true)
            {
                log.InfoFormat("Client connected :: {0}", client.Client.RemoteEndPoint);
                Byte[] bytes = new Byte[MAX_TCP_DATA];
                String data = null;
                NetworkStream stream = client.GetStream();

                int i;

                try
                {
                    // Loop to receive all the data sent by the client.
                    while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
                    {
                        // bytes contains received data in byte[].
                        // Translate data bytes to a UTF-8 string.
                        byte[] receivedBuffer = new byte[i];
                        Array.Copy(bytes, receivedBuffer, i);

                        if (log.IsDebugEnabled)
                        {
                            data = System.Text.Encoding.UTF8.GetString(receivedBuffer);
                            log.InfoFormat("Received MSG ::: " + data);
                        }

                        CommEventArgs comEventArg = new CommEventArgs();
                        comEventArg.data = receivedBuffer;
                        IPEndPoint remoteIPEndPoint = (IPEndPoint)client.Client.RemoteEndPoint;
                        comEventArg.srcAddress = remoteIPEndPoint.Address.ToString();
                        comEventArg.srcPort = remoteIPEndPoint.Port;
                        comEventArg.length = i;
                        this.OnDataReceived(comEventArg);
                    }
                }
                catch (Exception ex)
                {
                    log.InfoFormat("Client disconnected : {0}", client.Client.RemoteEndPoint);
                }
                finally
                {
                   client.Close();
                }
            }
        }

, когда яотправлено байтового массива 40000. Мой TCP-сервер получает только 26280 байт.

Скажите, пожалуйста, в чем проблема при получении.

Ответы [ 3 ]

5 голосов
/ 18 октября 2010

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

This:

while ((i = stream.Read (bytes, 0, bytes.Length))! = 0)

Не читает все данные, отправленные клиентом, но все данные, полученные сервером.Это может быть не полным.

Вам нужно зайти в документацию и сделать домашнее задание, то есть прочитать его.

В нем говорится:

Операция чтениябудет считывать столько данных, сколько доступно, вплоть до количества байтов, указанного параметром size.

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

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

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

Если данные для чтения недоступны, метод NetworkStream.Read будет блокироваться до тех пор, пока данные не станут доступны.

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

Подсказка: чтение документации - это не излишняя вещь.В вашем случае вы принимаете поведение, которого явно нет в соответствии с документацией.

3 голосов
/ 18 октября 2010

Похоже, вы пытаетесь прочитать все данные одновременно.NetworkStream не работает, как вы ожидали.Вы должны прочитать поток небольшими порциями и скопировать в полученный буфер, если хотите получить все ожидаемые данные.

В вашем случае вы, вероятно, получите 13720 байт на первой итерации и 26280 байт на второй.Как я уже говорил, лучше читать небольшими порциями, такими как 64/256/1024 байта и т. Д. (Особенно в медленной сетевой среде).

1 голос
/ 18 октября 2010

В вашем цикле while вы не гарантированно получите больше данных, чем 64 Кб одновременно.Получаете ли вы 26280 при первом чтении в цикле или всего за все чтения?

Обычно вам сначала нужно прочитать весь поток, а затем посмотреть, сколько у вас байтов

List<byte> allBytes = new List<byte>(MAX_TCP_DATA);
int i;
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
    allBytes.AddRange( allBytes.Take(i) );
}
Console.WriteLine(allBytes.Count);
string data = System.Text.Encoding.UTF8.GetString(allBytes.ToArray());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...