【问题标题】:Prevent exception if buffer is too small?如果缓冲区太小,防止异常?
【发布时间】:2012-02-12 01:51:10
【问题描述】:

每当我的服务器应用程序收到一个对于缓冲区来说太大的数据包时,它就会在调用 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,因此我不得不将其翻译回来。

ReceiveFromCallback 的“缓冲区”变量仅包含消息的前 64 个字节(如果大于该值)。因此检查“缓冲区”是否包含超过 64 个字节不是一种选择。

所以我的问题是:

我是否需要调用 EndReceiveFrom();为什么要调用它?如何检查接收到的消息对于缓冲区是否太大?

【问题讨论】:

    标签: c# arrays sockets asynchronous udp


    【解决方案1】:

    From MSDN:

    在回调方法中,调用IAsyncResult的AsyncState方法,获取传递给BeginReceiveFrom方法的状态对象。从此状态对象中提取接收 Socket。获取Socket后,可以调用EndReceiveFrom方法成功完成读取操作,返回读取的字节数。

    因此,您应该在回调中调用 EndReceiveFrom(就像您一样)。只需捕获异常,您的应用程序就不会“崩溃”。

    【讨论】:

    • 谢谢。但我只想在没有其他方法防止崩溃时捕获异常。
    • 处理它的唯一方法是捕获异常。这样做并没有错。这是一个持续的错误。只需在调用周围加上一个 try { ... } catch (SocketException e) { }。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-03
    • 2013-02-10
    • 1970-01-01
    相关资源
    最近更新 更多