Предотвратить исключение, если буфер слишком мал? - PullRequest
1 голос
/ 12 февраля 2012

Всякий раз, когда мое серверное приложение получает слишком большой для буфера пакет, оно вызывает сбой при вызове Socket.EndReceiveFrom.Вот как выглядит мой код:

static EndPoint remote = new IPEndPoint(IPAddress.Any, 0);
static Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

static void Main(string[] args)
{
    socket.Bind(new IPEndPoint(IPAddress.Any, 1234));
    Receive();
    Console.WriteLine("Receiving ...");

    for (; ; ) ;
}

static void Receive()
{
    byte[] buffer = new byte[64];
    socket.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref remote, ReceiveFromCallback, buffer);
}

static void ReceiveFromCallback(IAsyncResult result)
{
    EndPoint theRemote = new IPEndPoint(IPAddress.Any, 0);
    byte[] buffer = (byte[])result.AsyncState;

    // the following for loop is irrelevant for this question - it simply outputs the received data as hex numbers
    for (int x = 0; x < 8; x++)
    {
        Console.Write("  ");
        for (int y = 0; y < 8; y++)
        {
            string hex = Convert.ToString(buffer[(x * 8) + y], 16);
            Console.Write((hex.Length == 1 ? "0" : "") + hex + " ");
        }
        Console.WriteLine();
    }

    // the following line of code crashes the application if the received message is larger than 64 bytes
    socket.EndReceiveFrom(result, ref theRemote);
}

Если размер полученных пакетов превышает 64 байта, мое приложение выдает исключение SocketException, говоря следующее:

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

Обратите внимание, что это не исходный текст сообщения.Так как я работаю с немецкой версией Visual Studio, мне пришлось перевести ее обратно.

Переменная «buffer» ReceiveFromCallback содержит только первые 64 байта сообщения, если он больше этого.Поэтому проверять, содержит ли «буфер» более 64 байтов, не вариант.

Поэтому у меня следующие вопросы:

Нужно ли вызывать EndReceiveFrom ();почему это должно называться?Как я могу проверить, является ли полученное сообщение слишком большим для буфера?

1 Ответ

2 голосов
/ 12 февраля 2012

От MSDN:

В методе обратного вызова вызовите метод AsyncState объекта IAsyncResult, чтобы получить объект состояния, переданный методу BeginReceiveFrom. Извлеките получающее гнездо из этого объекта состояния. После получения Socket вы можете вызвать метод EndReceiveFrom, чтобы успешно завершить операцию чтения и вернуть количество прочитанных байтов.

Следовательно, вы должны вызывать EndReceiveFrom в обратном вызове (как вы делаете). Просто поймайте исключение, и ваше приложение не будет аварийно завершено.

...