如果缓冲区太小,防止异常?

发布于 2025-01-04 21:42:07 字数 1728 浏览 3 评论 0原文

每当我的服务器应用程序收到一个对于缓冲区来说太大的数据包时,它就会在调用 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 的“buffer”变量仅包含消息的前 64 个字节(如果它大于该值)。因此检查“buffer”是否包含超过 64 个字节不是一个选项。

所以我的问题是:

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

Whenever my server application receives a packet which is too big for the buffer, it crashes when calling Socket.EndReceiveFrom. This is what my code looks like:

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);
}

If the received packets is larger than 64 bytes, my application throws a SocketException saying the following:

A message which was sent over the datagram socket was too large for
the internal data buffer or another network limit, or the buffer used
for receiving the datagram was too small.

Notice that this is not the original message text. Since I'm working with the German version of Visual Studio, I had to translate it back.

ReceiveFromCallback's "buffer" variable only contains the first 64 bytes of the message if it's larger than that. So checking whether "buffer" contains more than 64 bytes is not an option.

So my questions are:

Do I need to call EndReceiveFrom(); why should it be called? How can I check whether the received message is too big for the buffer?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

江南烟雨〆相思醉 2025-01-11 21:42:07

来自 MSDN:

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

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

From MSDN:

Within the callback method, call the AsyncState method of the IAsyncResult to obtain the state object passed to the BeginReceiveFrom method. Extract the receiving Socket from this state object. After obtaining the Socket, you can call the EndReceiveFrom method to successfully complete the read operation and return the number of bytes read.

Therefore, you should call EndReceiveFrom in the callback (like you do). Simply catch the exception and your application wont "crash".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文