gpt4 book ai didi

c++ - 在 WSASend 之后处理 LPWSAOVERLAPPED

转载 作者:行者123 更新时间:2023-11-28 07:49:57 25 4
gpt4 key购买 nike

我目前正在用托管 C++ 编写一个 winsock 服务器端套接字。创建 LPWSAOVERLAPPED 对象并将其传递给 WSASend 函数后,我看不到在非阻塞操作完成时将其删除的位置(WSASend 返回 SOCKET_ERROR,WSAGetLastError() 返回 WSA_IO_PENDING)。我当前的解决方案是创建一个 System::Threading::WaitHandle,获取指向等待句柄的不安全指针并将其传递到 LPWSAOVERLAPPED 对象下的 hEvent。但是,这会导致不必要的对象创建,因为我并不真正关心发送操作何时完成。另一方面,我需要一个 LPWSAOVERLAPPED 对象以使操作完全非阻塞。有没有人有更好的解决方案来解决这个问题?这是我当前的代码:

void Connectivity::ConnectionInformation::SendData(unsigned char data[], const int length)
{
if (isClosed || sendError)
return;

Monitor::Enter(this->sendSyncRoot);
try
{
LPWSAOVERLAPPED overlapped = OverlappedObjectPool::GetOverlapped();
WaitHandle ^ handle = gcnew ManualResetEvent(false);
IntPtr handlePointer = handle->SafeWaitHandle->DangerousGetHandle();

sendInfo->buf = (char*)data;
sendInfo->len = length;

overlapped->Internal = 0;
overlapped->InternalHigh = 0;
overlapped->Offset = 0;
overlapped->OffsetHigh = 0;
overlapped->Pointer = 0;
overlapped->hEvent = (void*)handlePointer; //Set pointer

if (WSASend(connection, sendInfo, 1, NULL, 0, overlapped, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() == WSA_IO_PENDING)
{
ThreadPool::UnsafeRegisterWaitForSingleObject(handle, sentCallback, (IntPtr)((void*)overlapped), -1, true);
}
else
{
this->sendError = true;
//The send error bool makes sure that the close function doesn't get called
//during packet processing which could lead to a lot of null reffernce exceptions.
OverlappedObjectPool::GiveObject(overlapped);
}
}
else
{
handle->Close();
sentData((IntPtr)((void*)overlapped), false);
}
}
finally
{
Monitor::Exit(this->sendSyncRoot);
}
}

最佳答案

对于异步 I/O,通过调用完成例程或将 IOCP 完成消息排队到 IOCP 完成队列来通知完成。在这两种情况下,都应该注意 OVL 结构应该至少有整个异步操作的生命周期,但如果方便的话可以更长:)

在完成例程的情况下,OVL 中未使用的 hEvent 参数可用于传输指向“IOrequest”类实例的指针,该实例包含数据缓冲区、WSABUF 数组和 OVL 结构作为成员,(并且肯定是指向已为其发出 I/O 的套接字对象的指针)。 OVL 指针作为完成例程的参数提供,因此可以检索 hEvent 并将其转换为类类型,从而检索完整的类实例 - OVL、数据缓冲区等。当数据已被处理时,(或立即在WSASend 情况下的完成例程),并且此 IOrequest 最终被销毁(或重新合并),OVL 将随之销毁。这听起来有点乱伦,但效果很好,不需要任何讨厌的宏或其他技巧。

类似的方法可以用于完整的 IOCP,或者作为 lpCompletionKey“备用”参数传递的 OVL。

哦 - 你确实关心操作是否完成 - 你至少需要检查错误。

关于c++ - 在 WSASend 之后处理 LPWSAOVERLAPPED,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14042734/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com