Socket.EndAccept 抛出 ArgumentException
Socket.EndAccept throwing ArgumentException
使用 .NET 6.0。
我这样调用了 BeginAccept:
AsyncCallback callback = new AsyncCallback(AcceptCallback);
object? state = this.listenSocket;
_ = this.listenSocket.BeginAccept(callback, state);
并且我的 AcceptCallback
方法按预期被调用。然后我必须调用 EndAccept
来获取接收套接字:
private static void AcceptCallback(IAsyncResult result)
{
Socket? listenSocket = result.AsyncState as Socket;
if (listenSocket == null)
{
// note: This is impossible but it helps getting the possible
// null reference warnings out of the way.
throw new ArgumentNullException(nameof(result.AsyncState), "The state object is null.");
}
Socket receiveSocket = listenSocket.EndAccept(
out byte[] buffer,
out int bytesRead,
result); // and here it blows up
最后一个电话给我一个“System.ArgumentException:'值不在预期范围内。(参数'asyncResult')'”。
显然最后一个参数有问题。这不是我提供的东西,它是系统传递给我的结果参数,它(根据调试器)是一个正确的 System.Threading.Tasks.TaskToApm.TaskAsyncResult。我只是按照我找到的示例进行操作。
我一开始在 BeginAccept
的调用中没有包装 new AsyncCallback()
因为我不明白它有什么好处(虽然我想知道)。我最初也有非静态方法。因为我遇到了这个问题,所以我将其更改为更像原始示例,但仍然存在相同的异常。
问题是什么,我该怎么做才能克服它?
[编辑]
正如 Hans Passant 所指出的,结果参数不应该是 System.Threading.Tasks.TaskToApm.TaskAsyncResult
,这会导致错误。互联网上几乎没有关于 TaskAsyncResult 的讨论或文档,这让我产生了怀疑,认为这可能是新框架代码中的错误。所以我用 .NET 5.0 重建,但结果是一样的。
我只是在使用 System.Net.Sockets.Socket 类,没有什么特别的自定义库或类似的东西。
第一位出现:
AsyncCallback callback = new AsyncCallback(AcceptCallback);
object? state = this.listenSocket;
_ = this.listenSocket.BeginAccept(callback, state);
让它失败。如果我将其更改为:
int maxSize = 0x2000; // 8K
AsyncCallback callback = new AsyncCallback(AcceptCallback);
object? state = this.listenSocket;
_ = this.listenSocket.BeginAccept(maxSize, callback, state);
它成功了,在 EndAccept 上不再有异常,我在 ReceiveCallback 中获得了预期的数据(异步流程的下一步)。
因为我是套接字编程的新手,所以我认为从简单开始是明智的,所以我使用参数最少的 BeginAccept 重载。我假设它会使用默认的最大尺寸。好吧,无论那个“简单”的重载做什么,都不好。
所以 AcceptCallback
的结果参数的类型 System.Threading.Tasks.TaskToApm.TaskAsyncResult
完全没问题,那里没有问题(我检查过,它仍然是一样的)。
我可以继续了。
使用 .NET 6.0。
我这样调用了 BeginAccept:
AsyncCallback callback = new AsyncCallback(AcceptCallback);
object? state = this.listenSocket;
_ = this.listenSocket.BeginAccept(callback, state);
并且我的 AcceptCallback
方法按预期被调用。然后我必须调用 EndAccept
来获取接收套接字:
private static void AcceptCallback(IAsyncResult result)
{
Socket? listenSocket = result.AsyncState as Socket;
if (listenSocket == null)
{
// note: This is impossible but it helps getting the possible
// null reference warnings out of the way.
throw new ArgumentNullException(nameof(result.AsyncState), "The state object is null.");
}
Socket receiveSocket = listenSocket.EndAccept(
out byte[] buffer,
out int bytesRead,
result); // and here it blows up
最后一个电话给我一个“System.ArgumentException:'值不在预期范围内。(参数'asyncResult')'”。
显然最后一个参数有问题。这不是我提供的东西,它是系统传递给我的结果参数,它(根据调试器)是一个正确的 System.Threading.Tasks.TaskToApm.TaskAsyncResult。我只是按照我找到的示例进行操作。
我一开始在 BeginAccept
的调用中没有包装 new AsyncCallback()
因为我不明白它有什么好处(虽然我想知道)。我最初也有非静态方法。因为我遇到了这个问题,所以我将其更改为更像原始示例,但仍然存在相同的异常。
问题是什么,我该怎么做才能克服它?
[编辑]
正如 Hans Passant 所指出的,结果参数不应该是 System.Threading.Tasks.TaskToApm.TaskAsyncResult
,这会导致错误。互联网上几乎没有关于 TaskAsyncResult 的讨论或文档,这让我产生了怀疑,认为这可能是新框架代码中的错误。所以我用 .NET 5.0 重建,但结果是一样的。
我只是在使用 System.Net.Sockets.Socket 类,没有什么特别的自定义库或类似的东西。
第一位出现:
AsyncCallback callback = new AsyncCallback(AcceptCallback);
object? state = this.listenSocket;
_ = this.listenSocket.BeginAccept(callback, state);
让它失败。如果我将其更改为:
int maxSize = 0x2000; // 8K
AsyncCallback callback = new AsyncCallback(AcceptCallback);
object? state = this.listenSocket;
_ = this.listenSocket.BeginAccept(maxSize, callback, state);
它成功了,在 EndAccept 上不再有异常,我在 ReceiveCallback 中获得了预期的数据(异步流程的下一步)。
因为我是套接字编程的新手,所以我认为从简单开始是明智的,所以我使用参数最少的 BeginAccept 重载。我假设它会使用默认的最大尺寸。好吧,无论那个“简单”的重载做什么,都不好。
所以 AcceptCallback
的结果参数的类型 System.Threading.Tasks.TaskToApm.TaskAsyncResult
完全没问题,那里没有问题(我检查过,它仍然是一样的)。
我可以继续了。