FD_WRITE触发条件:
1.client 通过connect(WSAConnect)首次和server建立连接时,在client端会触发FD_WRITE事件
2.server通过accept(WSAAccept)接受client连接请求时,在server端会触发FD_WRITE事件
3.send(WSASend)/sendto(WSASendTo)发送失败返回WSAEWOULDBLOCK,并且当缓冲区有可用空间时,则会触发FD_WRITE事件
第1.2条其实是同一种情况,在第一次建立连接时,C/S端都会触发一个FD_WRITE事件。
主要是3这种情况:send出去的数据其实都先存在winsock的发送缓冲区中,然后才发送出去,如果缓冲区满了,那么再调用send(WSASend,sendto,WSASendTo)的话,就会返回一个 WSAEWOULDBLOCK的错误码,接下来随着发送缓冲区中的数据被发送出去,缓冲区中出现可用空间时,一个 FD_WRITE 事件才会被触发,这里比较容易混淆的是 FD_WRITE 触发的前提是 缓冲区要先被充满然后随着数据的发送又出现可用空间 ,而不是缓冲区中有可用空间,
FD_READ事件触发条件:
1.在数据到达socket后,并且从来没有触发过FD_READ(也就是最开始的阶段)
2.在数据到达socket后,并且前一个recv()调用后
3.调用recv()后,缓冲区还有未读完的数据
FD_READ过程如下:
1.100 bytes 数据到达,winsock2发出FD_READ
2.程序用recv()只读入50 bytes,还剩下50 bytes
3.winsock2继续发出FD_READ消息
recv()返回WSAEWOULDBLOCK的情况:
1.有数据到达,FD_READ触发,该消息加入程序的消息队列
2.在还没处理该消息前,程序就把数据recv()了
3.等到处理该FD_READ消息时,程序调用recv()就会返回WSAEWOULDBLOCK(因为数据在这之前就recv()了)
FD_READ注意:
1.winsock2发出一个FD_READ后,如果程序没有用recv(),即使还有数据没接收FD_READ也不会再触发另一个FD_READ,要等到recv()调用后FD_READ才会发出。
2.对一个FD_READ多次recv()的情形:如果程序对一个FD_READ多次recv()将会造成触发多个空的FD_READ,所以程序在第2次recv()前要关掉FD_READ(可以使用WSAAsynSelect关掉FD_READ),然后再多次recv()。
1.client 通过connect(WSAConnect)首次和server建立连接时,在client端会触发FD_WRITE事件
2.server通过accept(WSAAccept)接受client连接请求时,在server端会触发FD_WRITE事件
3.send(WSASend)/sendto(WSASendTo)发送失败返回WSAEWOULDBLOCK,并且当缓冲区有可用空间时,则会触发FD_WRITE事件
第1.2条其实是同一种情况,在第一次建立连接时,C/S端都会触发一个FD_WRITE事件。
主要是3这种情况:send出去的数据其实都先存在winsock的发送缓冲区中,然后才发送出去,如果缓冲区满了,那么再调用send(WSASend,sendto,WSASendTo)的话,就会返回一个 WSAEWOULDBLOCK的错误码,接下来随着发送缓冲区中的数据被发送出去,缓冲区中出现可用空间时,一个 FD_WRITE 事件才会被触发,这里比较容易混淆的是 FD_WRITE 触发的前提是 缓冲区要先被充满然后随着数据的发送又出现可用空间 ,而不是缓冲区中有可用空间,
因此,作为一个应用程序,自收到首条FD_WRITE消息开始,便应认为自己必然能在一
个套接字上发出数据,直至一个send、WSASend、sendto或WSASendTo返回套接字错误
WSAEWOULDBLOCK。经过了这样的失败以后,要再用另一条FD_WRITE通知应用程序再
次发送数据。
FD_READ事件触发条件:
1.在数据到达socket后,并且从来没有触发过FD_READ(也就是最开始的阶段)
2.在数据到达socket后,并且前一个recv()调用后
3.调用recv()后,缓冲区还有未读完的数据
FD_READ过程如下:
1.100 bytes 数据到达,winsock2发出FD_READ
2.程序用recv()只读入50 bytes,还剩下50 bytes
3.winsock2继续发出FD_READ消息
recv()返回WSAEWOULDBLOCK的情况:
1.有数据到达,FD_READ触发,该消息加入程序的消息队列
2.在还没处理该消息前,程序就把数据recv()了
3.等到处理该FD_READ消息时,程序调用recv()就会返回WSAEWOULDBLOCK(因为数据在这之前就recv()了)
FD_READ注意:
1.winsock2发出一个FD_READ后,如果程序没有用recv(),即使还有数据没接收FD_READ也不会再触发另一个FD_READ,要等到recv()调用后FD_READ才会发出。
2.对一个FD_READ多次recv()的情形:如果程序对一个FD_READ多次recv()将会造成触发多个空的FD_READ,所以程序在第2次recv()前要关掉FD_READ(可以使用WSAAsynSelect关掉FD_READ),然后再多次recv()。
3.recv()返回WSAECONNABORTED,WSAECONNRESET...等消息,可以不做任何处理,可以等到FD_CLOSE事件触发时再处理