每当我的服务器应用程序收到一个对缓冲区来说太大的数据包时,它在调用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();为什么要这么称呼?如何检查收到的消息对于缓冲区是否太大?
答案 0 :(得分:2)
在回调方法中,调用IAsyncResult的AsyncState方法以获取传递给BeginReceiveFrom方法的状态对象。从此状态对象中提取接收Socket。获取Socket后,可以调用EndReceiveFrom方法成功完成读操作并返回读取的字节数。
因此,您应该在回调中调用EndReceiveFrom(就像您一样)。只需捕获异常,您的应用程序就不会“崩溃”。