如何使用WSASend()和IOCP模拟阻塞send()?

时间:2015-02-24 21:26:55

标签: c++ sockets winapi network-programming iocp

编辑: 这个问题不是必需的,因为WSASend()函数可以固有地用于阻塞模式,即使套接字具有重叠属性并且与完成端口相关联。要在阻止模式下使用它:在调用WSASend() 时,不要提供重叠结构或完成例程。


我想确保在发送数据时,只有在将此数据放入发送缓冲区时,该函数才会返回。所以这就是我提出的(伪代码):

void WSASend_Block(char *arr, int length)
{
    OVERLAPPED overlapped;
    overlapped.hEvent = someEvent;
    int result = WSASend(arr, length, &overlapped);

    while(true)
    {
        if (result == 0) // IO operation has been scheduled
        {
            wait(overlapped.hEvent, INFINITE); // block until data is placed into send buffer
            break;
        }
        else
        {
            result = WSASend(arr, length, &overlapped);
        }
    }
}

1 个答案:

答案 0 :(得分:4)

你为什么要这样做?

您认为它实现了什么?

来自WSASend的{​​{3}}

  

对于具有重叠属性的套接字,WSASend使用重叠的I / O.   除非lpOverlapped和lpCompletionRoutine参数都是   空值。在这种情况下,套接字被视为非重叠套接字。

因此,根本不提供完成例程或OVERLAPPED结构,并且呼叫将成为"非重叠"呼叫。这是你想要的,一个阻塞的呼叫,直到数据被复制到网络堆栈的发送缓冲区......

另外,我希望有问题的代码不会使用IOCP,因为它会崩溃,如果它可能不是现在,但最终会崩溃。你有竞争条件。如果您正在使用IOCP,则OVERLAPPED结构必须存在,直到完成发生并由调用GetQueuedCompletionStatus()的线程处理。您可以通过这种方式使用重叠I / O,只是不要将套接字与IOCP相关联。您等待事件发出信号的事实并不意味着您在GetQueuedCompletionStatus()上阻塞的某个线程将检索完成并处理它并完成触及您在上创建的OVERLAPPED结构在事件调用等待之前的堆栈完成并且该函数返回。