是否有可能无法获得WSASend呼叫的完成?

时间:2011-03-30 13:05:29

标签: c winapi tcp winsock2 iocp

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

我有一个奇怪的情况,它似乎没有为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.
}

2 个答案:

答案 0 :(得分:2)

您是否正在使用任何时髦的新功能,例如使用FILE_SKIP_COMPLETION_PORT_ON_SUCCESS关闭成功通话的完成次数?

您是否正在对您的发送进行任何形式的流量控制,或者只是在您想要的时候和您想要的频率发送?你可能会看到的只是一个SLOW完成,因为TCP堆栈正在进行拥塞控制而无法发送你的数据。如果您继续以不受控制的方式发送数据,您通常会遇到完成时间越来越长的情况。特别是如果您以比TCP连接成功获取数据的速度更快的速度发送数据,特别是如果TCP窗口不是那么大。有关更多信息,请参见此处:http://www.lenholgate.com/blog/2008/07/write-completion-flow-control.html

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

请注意,使用FILE_SKIP_COMPLETION_PORT_ON_SUCCESS时,WSARecv()和UDP存在一个已知错误(完全与您的问题无关),这就说明了您描述数据报是否大于您的缓冲区的情况供应和WSARecv()调用会产生WSAEMOREDATA;见这里:http://www.lenholgate.com/blog/2010/01/file-skip-completion-port-on-success-and-datagram-socket-read-errors.html

答案 1 :(得分:1)

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

来自GetQueuedCompletionStatus的文档:

  

即使您已通过功能a   与a关联的文件句柄   完成端口和有效的OVERLAPPED   结构,应用程序可以防止   完成端口通知。这是   通过指定有效事件来完成   处理hEvent成员的   OVERLAPPED结构,并设置它   低位。有效的事件句柄   其低位设置保持I / O.   从排队到完成   完成港口。