我accept一个socket,并将该socket与先前建立的一个完成端口建立了关联,然后就投递了一个WSASend操作,在GetQueuedCompletionStatus返回前,我又想投递一个WSARecv操作该怎么办?
就是说不想按照Send-Recv-Send-Recv这种固定的顺序来进行,可以以任意的顺序来进行收发操作。
是不是要建立两个overlap?
如果建立两个了,那么GetQueuedCompletionStatus得到的Overlap结构是send的overlap还是recv的overlap了?

解决方案 »

  1.   

    理论上来讲,WSASend是肯定会返回的,但是WSARecv在没有收到数据,并且Socket未断开之前正常情况下不会返回。
      

  2.   

    是要2个OverLapped Plus结构,通过扩展flag字段,标记与之关联的WSASend/WSARecv,也可以再扩展其他字段,记录投递的Io的逻辑含义
      

  3.   

    用GetQueuedCompletionStatus的第3个参数,进程上下文来获得和设置当前的操作,如:你在WSASend时,设置上下文句柄是Write操作,用GetQueuedCompletionStatus获得overlap之后,可判断该上下文的操作码是Write还是Read,Write对应WSASend,Read对应WSARecv
      

  4.   

     在tcp通讯过程中,不论采用什么io方式,具体的数据收发都是由系统地层完成的,我们所关心的只是什么时候应该接收什么时候应该发送.关于发送的时机我们自己是知道的,你想什么时候发就什么时候发啦.难点在于什么时候接收,也就是怎么知道有数据到达呢.最笨的方式是不停的轮询检查,如果有数就接收(数据先到达socket缓存,需要我们把数据取出来);更聪明的方法windows为我们提供了好几种io方式,甚至提供了完成端口这种bt的io方式.但不论io方式怎么bt和复杂,我们关心的永远是接收数据,发送数据只要按照具体的规定和格式投递出去就好了,具体操作教给机制去完成.所以在完成端口编程中我们也只关心数据的接收包括数据到达的通知方式/判断与接收处理等等.
     补充:虽然我们不关心发送操作,但GetQueuedCompletionStatus函数得到的结果是一次WSASend或WSARecv的结果具体是什么操作却没有明确标识,所以在程序处理中当我们要发送数据时可先在iokey中设置一个标志量来标识读或写操作,默认为读操作,当要发送数据时先置该标志量为写(此操作是随时随地的),在工作者线程中当GetQueuedCompletionStatus函数有结果,则可判断下标志量,如果是写则改为读,不需要另做其它工作(因为数据已经发送完毕了),如果是读则调用WSARecv函数读取数据.
        以上是我前些日子弄完成端口时的手记,但由于刚转vc,很多基础的东西还很欠缺,所以一直在补,所以没有用程序验证,不知道准确不准确,给楼主参考,同时也请高手指出错误.
        另外楼主说的是否建立OverLapped结构的问题,我的理解是每一次i/o操作都要见立一个OverLapped结构吧,并且这个结构在i/o操作完成时释放.
      

  5.   

    发送和接收各建立一个OverLapped Plus结构,里面丢个flag,比如: 
    m_bIsRecv,true就是recv,false就是send
    -------------------------------------------------------
    广告:VC/WinAPI 网络/多线程讨论 QQ群, 群号:41356711
      

  6.   

    搞两个OVERLAPPED扩展结构,enum ioDirection
    {
        __ioSend=0,
        __ioRecv
    };typede struct _tagIocpOverlapped
    {
         WSAOVERLAPPED; //注意这个的位置
         ioDirection ioDir;
         ..................
         ..................
    }IocpOverlapped ,*LPIocpOverlapped;分别用于接收发送,在发送前先设置好是发送还是读取,这个结构在GetQueuedCompletionStatus会还给你的,你通过里边的ioDir来判断