C # Async TCP-сокеты: обработка размера буфера и огромные передачи - PullRequest
4 голосов
/ 10 апреля 2011

При использовании блокирующего TCP-сокета мне не нужно указывать размер буфера. Например:

using (var client = new TcpClient())
{
    client.Connect(ServerIp, ServerPort);

    using (reader = new BinaryReader(client.GetStream()))
    using (writer = new BinaryWriter(client.GetStream()))
    {
        var byteCount = reader.ReadInt32();
        reader.ReadBytes(byteCount);
    }
}

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

Однако, при использовании асинхронных TCP-сокетов, мне нужно создать буфер и таким образом жестко закодировать максимальный размер:

 var buffer = new byte[BufferSize];
 socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, callback, null);

Я мог бы просто установить размер буфера, скажем, 1024 байта. Это сработает, если мне нужно только получать небольшие порции данных. Но что, если мне нужно получить сериализованный объект размером 10 МБ? Я мог бы установить размер буфера 10 *1024* 1024 ... но это потратило бы постоянные 10 МБ ОЗУ на время работы приложения. Это глупо.

Итак, мой вопрос: Как эффективно получать большие порции данных с помощью асинхронных TCP-сокетов?

1 Ответ

5 голосов
/ 10 апреля 2011

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

Редактировать 0:

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

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

...