WSASend后LPWSA重叠的处理 我现在在托管C++中编写了一个Winsock服务器端套接字。创建LPWSAOVERLAPPED对象并将其传递给WSASend函数后,我看不到在操作完成非阻塞时在何处删除它(WSASend返回SOCKET_ERROR,WSAGetLastError()返回WSA_IO_PENDING)。我当前的解决方案是创建System::Threading::WaitHandle,获取指向等待句柄的不安全指针,并将其传递到LPWSAOVERLAPPED对象下的hEvent。但是,这会导致不必要的对象创建,因为我并不真正关心发送操作何时完成。另一方面,我需要一个LPWSAOoverlapped对象,以便使操作完全无阻塞。有谁有更好的解决办法吗?这是我目前的代码: 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); } }

WSASend后LPWSA重叠的处理 我现在在托管C++中编写了一个Winsock服务器端套接字。创建LPWSAOVERLAPPED对象并将其传递给WSASend函数后,我看不到在操作完成非阻塞时在何处删除它(WSASend返回SOCKET_ERROR,WSAGetLastError()返回WSA_IO_PENDING)。我当前的解决方案是创建System::Threading::WaitHandle,获取指向等待句柄的不安全指针,并将其传递到LPWSAOVERLAPPED对象下的hEvent。但是,这会导致不必要的对象创建,因为我并不真正关心发送操作何时完成。另一方面,我需要一个LPWSAOoverlapped对象,以便使操作完全无阻塞。有谁有更好的解决办法吗?这是我目前的代码: 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); } },c++,winapi,memory,c++-cli,winsock,C++,Winapi,Memory,C++ Cli,Winsock,对于异步I/O,通过调用完成例程或将IOCP完成消息排入IOCP完成队列来通知完成。在这两种情况下,应注意OVL结构的生存期至少应为整个异步操作,但如果方便的话,可以更长:) 在完成例程的情况下,OVL中未使用的hEvent参数可用于传输指向“IOrequest”类实例的指针,该类实例包含数据缓冲区、WSABUF数组和OVL结构作为成员(当然还有指向已为其发出I/O的套接字对象的指针)。OVL指针作为参数提供给完成例程,因此可以检索hEvent并将其转换为类类型,从而在处理数据时检索完整的类实例

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

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

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


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

更好的解决方案:使用本机或纯托管代码(在最后一种情况下,用C#编写)。为什么你需要如此奇怪的混合解决方案?是的,有一种更好的方法,使用Socket::BeginSend()。使用WSASend()没有任何好处这里。socket类占用了太多内存,转到较低的级别可以解决这个问题,这就是为什么我在MSDN上使用纯winsock方法。他们说,如果lpOverlapped和lpCompletionRoutine都为null,操作将被视为阻塞。但是,要执行完成例程,它需要重叠结构和重叠IOo需要重叠结构。当测试时,重叠数据设置为NULL,且完成例程为空,我从未收到任何WSA_IO_挂起。我的套接字是否以非阻塞方式执行操作?