размер следующей дейтаграммы в очереди - UDP - PullRequest
6 голосов
/ 10 декабря 2011

Я использую класс System.Net.Sockets Socket для получения дейтаграмм UDP. Я хотел знать точную длину полученной дейтаграммы, чтобы проверить достоверность дейтаграммы.

Socket.Receive(Byte()) документация по методу гласит:

Если вы используете Socket без соединения, Receive будет читать первую дейтаграмму в очереди с адреса получателя, указанного вами в методе Connect. Если полученная датаграмма больше размера параметра буфера, буфер заполняется первой частью сообщения, лишние данные теряются и выдается исключение SocketException.

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

Есть ли способ узнать размер следующей дейтаграммы?

public static void Receive()
{
    Byte[] buf, discardbuf;
    const int paklen = 32;                  //correct packet length
    int l;

    buf = new Byte[paklen];
    discardbuf = new Byte[4096];

    while (rcv_enable)
    {
        l = soc.Available;
        if (l == 0) continue;
        if (l == paklen) soc.Receive(buf);  //receive the correct packet
        else soc.Receive(discardbuf);       //discard otherwise
        Thread.Sleep(200);
        Console.WriteLine("Received {0}", l);
    };
}

Ответы [ 2 ]

3 голосов
/ 11 декабря 2011

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

Поскольку производительность, похоже, является проблемой, и вы хотите избежать исключений, я бы посмотрел на перегрузку для Receive , которая возвращает необработанную ошибку сокета вместо выдачи исключений . Документация MSDN (неправильно?) Заявляет, что этот метод тоже вызовет исключение, но я не думаю, что это так. Это определенно стоит попробовать.

SocketError error;
byte[] buffer = new byte[512]; // Custom protocol max/fixed message size
int c = this.Receive(buffer, 0, buffer.Length, SocketFlags.None, out error);

if (error != SocketError.Success)
{
    if(error == SocketError.MessageSize)
    {
        // The message was to large to fit in our buffer
    }
}

Используйте буфер с заранее известным размером в здравом уме и используйте перегрузку, чтобы проверить код ошибки SocketError, чтобы определить, было ли чтение успешным или вы должны отбросить пакет.

Если, однако, ваш собственный протокол может отправлять дейтаграммы неизвестного размера вплоть до предела максимального размера дейтаграммы, у вас нет другого выбора, кроме как выделить буфер, достаточно большой, чтобы вместить самый большой пакет (65 КБ) (вы можете использовать пул буферов для избегайте проблем с памятью в зависимости от вашего кода).

Также ознакомьтесь с перечислением SocketFlags , в котором содержатся некоторые элементы, которые могут вас заинтересовать, например члены Partial и Peek.

2 голосов
/ 10 декабря 2011

Почему бы просто не проверить возвращаемое значение из Receive? Я уверен, что каждый вызов вернет одну дейтаграмму.

...