2

就像标题所说的那样,在与 I/O 完成端口关联的套接字上成功 WSASend调用是否有可能因为线程结束以外的任何原因不发布完成?

我有一个奇怪的情况,看起来没有为 a 发布完成WSASend,这导致套接字泄漏;应用程序认为套接字的发送仍处于挂起状态并拒绝释放它。

发送代码如下:

void CSocketServer::Write(
    Socket *pSocket,
    CIOBuffer *pBuffer) const
{
    pSocket->AddRef();

    pBuffer->SetOperation(IO_Write_Completed);
    pBuffer->SetupWrite();
    pBuffer->AddRef();

    DWORD dwFlags = 0;
    DWORD dwSendNumBytes = 0;

    if (SOCKET_ERROR == ::WSASend(
        pSocket->m_socket,
        pBuffer->GetWSABUF(), 
        1, 
        &dwSendNumBytes,
        dwFlags,
        pBuffer, 
        NULL))
    {
        DWORD lastError = ::WSAGetLastError();

        if (ERROR_IO_PENDING != lastError)
        {
            pSocket->OnConnectionError(WriteError, pBuffer, lastError);

            pSocket->WriteCompleted();  // this pending write will never complete...

            pSocket->Release();
            pBuffer->Release();
        }
    }
    // Note: even if WSASend returns SUCCESS an IO Completion Packet is 
    // queued to the IOCP the same as if ERROR_IO_PENDING was returned.
    // Thus we need no special handling for the non error return case.
    // See http://support.microsoft.com/default.aspx?scid=kb;en-us;Q192800
    // for details.
}
4

2 回答 2

2

您是否正在使用任何时髦的新功能,例如使用 关闭成功呼叫的完成FILE_SKIP_COMPLETION_PORT_ON_SUCCESS

您是否对发送进行了任何形式的流量控制,或者您只是在您喜欢的时候随时发送?您可能看到的只是一个缓慢的完成,因为 TCP 堆栈正在进行拥塞控制并且还不能发送您的数据。如果您继续以不受控制的方式发送数据,您通常会遇到完成时间越来越长的情况。特别是如果您以比 TCP 连接更快的速度发送数据,则可以成功地将数据发送到另一端,尤其是在 TCP 窗口不是那么大的情况下。有关更多信息,请参见此处:http ://www.lenholgate.com/blog/2008/07/write-completion-flow-control.html。

当然,这可能只是您的发送逻辑中的一个错误,您能发布一些代码吗?

请注意,使用 WSARecv() 和 UDP 时存在一个已知错误(因此与您的问题完全无关),FILE_SKIP_COMPLETION_PORT_ON_SUCCESS如果数据报大于您提供的缓冲区并且WSARecv()调用会生成一个WSAEMOREDATA; 见这里: http: //www.lenholgate.com/blog/2010/01/file-skip-completion-port-on-success-and-datagram-socket-read-errors.html

于 2011-03-31T07:48:22.567 回答
1

OVERLAPPED通过设置结构的有效低位可以防止完成端口发布hEvent

来自文档GetQueuedCompletionStatus

即使您向函数传递了与完成端口和有效的 OVERLAPPED 结构关联的文件句柄,应用程序也可以阻止完成端口通知。这是通过为 OVERLAPPED 结构的 hEvent 成员指定一个有效的事件句柄并设置其低位来完成的。设置低位的有效事件句柄可防止 I/O 完成排队到完成端口。

于 2011-03-31T13:52:00.133 回答