WSAAsynSelect()模型 FD_READ事件中recv()接收数据的返回值讨论!

街坊跳舞 2008-08-29 03:47:46
使用WSAAsynSelect()模型,在FD_READ事件的时候recv()的返回值讨论?


do
{
int nRecvStat = recv( m_sockID, pchBuf, nBufLen, 0 );
int nErrorCode = ::WSAGetLastError();
}while(nRecvStat > 0);


nRecvStat > 0 自然就是实际从SOCKET缓冲区中读出的数据,现在我们讨论nRecvStat
1. 这里什么情况下nRecvStat == 0?
2. 什么情况下nRecvStat < 0;
3. nRecvStat < 0 的情况下,nErrorCode == WSAEWOULDBLOCK(10035)号错误又是什么情况下发生的?这个大侠们好好给解释下。
4. nRecvStat < 0 的情况下,nErrorCode == WSAEMSGSIZE(10040)号错误又是什么情况下发生的?
5. 大家补充!

PS: 一定要记得是 WSAAsynSelect()模型。


...全文
842 12 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
dos5gw 2010-07-10
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 wineggdrop 的回复:]
你的代码本身就有逻辑上问题.
1.WSAAsynSelect()模型接收数据是有FD_READ时就接收,只要有数据可以读取,系统就会向你的程序发送FD_READ消息,使用循环去接收数据是"画蛇添足",而且会造成很多系统向你的程序发送的消息的丢失或被阻塞.只有阻塞socket模型才会使用你这种接收数据方式,WSAAsynSelect()调用的socket全是非阻塞的.

2.WSAAsynSe……
[/Quote]
恩,同意,在接到FD_READ消息后调用recv()或WSARecv(),是不可能返回 <=0的值的.
cattycat 2008-09-06
  • 打赏
  • 举报
回复
觉得4楼说得有道理。WSAAyncSelect是非阻塞模式,当数据到达,向窗口句柄发送消息,你在这个消息处理中接收数据。
World7th 2008-09-06
  • 打赏
  • 举报
回复

采用WSAAsyncSelect模型时
一个FD_READ对应一个recv,在WSAAsyncSelect模型下,如果注册了FD_CLOSE,FD_READ,接收到FD_READ后读取数据,是不会出现nRecvStat = 0的情况的,因为nRecvStat=0表示客户端连接断开,而这种情况下接收到的消息应该是FD_CLOSE,除非你在FD_CLOSE中再Post一个FD_READ,PostMessage(WM_SOCKET, wParam, FD_READ); 这样的话处理FD_READ,nRecvStat = 0
街坊跳舞 2008-09-05
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 WinEggDrop 的回复:]
既然你知道上面的规则,那你的代码还会使用循环去接收数据?
[/Quote]

使用循环接收,会触发WSAWOULDBLOCK(10035号)错误!

PS:我用循环是因为代码是最早的时候写的,那时候刚知道SOCKET 。。。 现在已经修改了。
walkbywind 2008-09-05
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 yyunffu 的回复:]
1楼高人已经回答的很精彩了。
一般用基于消息的异步通知实现网络通信,在有数据到达时,系统才会通知,一般应该不会出现问题。
[/Quote]
11000000 2008-09-03
  • 打赏
  • 举报
回复

学习。
WinEggDrop 2008-09-02
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 jiefangtw 的回复:]
FD_READ事件触发条件:
1.在数据到达socket后,并且从来没有触发过FD_READ(也就是最开始的阶段)
2.在数据到达socket后,并且前一个recv()调用后
3.调用recv()后,缓冲区还有未读完的数据

第3点过程如下:
1.100 bytes 数据到达,winsock2发出FD_READ
2.程序用recv()只读入50 bytes,还剩下50 bytes
3.winsock2继续发出FD_READ消息

recv()返回WSAEWOULDBLOCK的情况:
1.有数据到达,FD_READ触发,该消息加入程…
[/Quote]

既然你知道上面的规则,那你的代码还会使用循环去接收数据?
街坊跳舞 2008-09-02
  • 打赏
  • 举报
回复
FD_READ事件触发条件:
1.在数据到达socket后,并且从来没有触发过FD_READ(也就是最开始的阶段)
2.在数据到达socket后,并且前一个recv()调用后
3.调用recv()后,缓冲区还有未读完的数据

第3点过程如下:
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()了)

注意:
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事件触发时再处理

WinEggDrop 2008-08-30
  • 打赏
  • 举报
回复
你的代码本身就有逻辑上问题.
1.WSAAsynSelect()模型接收数据是有FD_READ时就接收,只要有数据可以读取,系统就会向你的程序发送FD_READ消息,使用循环去接收数据是"画蛇添足",而且会造成很多系统向你的程序发送的消息的丢失或被阻塞.只有阻塞socket模型才会使用你这种接收数据方式,WSAAsynSelect()调用的socket全是非阻塞的.

2.WSAAsynSelect()模型中使用recv()或WSARecv()接收数据(当有FD_READ消息被触发时),recv()或WSARecv()是根本不可能出现0的返回值.当有FD_READ时,数据已经是在你的系统的缓冲中的了,就算远程的socket断开,你还是可以接收到这些数据的,除非你的系统太繁忙或未分页内存等用光的特殊情况下,或者你自己将socket用closesocket()断开了,否则在接到FD_READ消息后调用recv()或WSARecv(),是不可能返回<=0的值的.
yyunffu 2008-08-29
  • 打赏
  • 举报
回复
1楼高人已经回答的很精彩了。
一般用基于消息的异步通知实现网络通信,在有数据到达时,系统才会通知,一般应该不会出现问题。
街坊跳舞 2008-08-29
  • 打赏
  • 举报
回复
Socket 错误描述
常数 值 描述
sckOutOfMemory 7 内存不足
sckInvalidPropertyValue 380 属性值无效。
sckGetNotSupported 394 属性不可读。
sckSetNotSupported 383 属性是只读的。
sckBadState 40006 所请求的事务或请求本身的错误协议或者错误连接状态。
sckInvalidArg 40014 传递给函数的参数格式不确定,或者不在指定范围内。
sckSuccess 40017 成功。
sckUnsupported 40018 不受支持的变量类型。
sckInvalidOp 40020 在当前状态下的无效操作
sckOutOfRange 40021 参数越界。
sckWrongProtocol 40026 所请求的事务或请求本身的错误协议
sckOpCanceled 1004 取消操作。
sckInvalidArgument 10014 所请求的地址是广播地址,但未设置标记。
sckWouldBlock 10035 套接字不成块,而指定操作将使之成块。
sckInProgress 10036 制造块的?Winsock?操作在进行之中。
sckAlreadyComplete 10037 完成操作。未进行制造块的操作。
sckNotSocket 10038 描述符不是套接字。
sckMsgTooBig 10040 数据报太大,不适于缓冲区的要求,因而被截断。
sckPortNotSupported 10043 不支持指定的端口。
sckAddressInUse 10048 地址在使用中。
sckAddressNotAvailable 10049 来自本地机器的不可用地址。
sckNetworkSubsystemFailed 10050 网络子系统失败。
sckNetworkUnreachable 10051 此时不能从主机到达网络。
sckNetReset 10052 在设置SO_KEEPALIVE?时连接超时。
sckConnectAborted 11053 由于超时或者其它失败而中止连接。
sckConnectionReset 10054 通过远端重新设置连接。
sckNoBufferSpace 10055 没有可用的缓冲空间。
sckAlreadyConnected 10056 已连接套接字。
sckNotConnected 10057 未连接套接字。
sckSocketShutdown 10058 已关闭套接字。
sckTimedout 10060 已关闭套接字。
sckConnectionRefused 10061 强行拒绝连接。
sckNotInitialized 10093 应首先调用WinsockInit。
sckHostNotFound 11001 授权应答:未找到主机。
sckHostNotFoundTryAgain 11002 非授权应答:未找到主机。
sckNonRecoverableError 11003 不可恢复的错误。
sckNoData 11004 无效名,对所请求的类型无数据记录。
cnzdgs 2008-08-29
  • 打赏
  • 举报
回复
1. 这里什么情况下nRecvStat == 0?
连接已经断开。

2. 什么情况下nRecvStat < 0;
没有接收到数据。

3. nRecvStat < 0 的情况下,nErrorCode == WSAEWOULDBLOCK(10035)号错误又是什么情况下发生的?这个大侠们好好给解释下。
socket设置了非阻塞,但目前没有数据。

4. nRecvStat < 0 的情况下,nErrorCode == WSAEMSGSIZE(10040)号错误又是什么情况下发生的?
使用UDP协议,缓冲区太小,接收数据不完整。

5. 大家补充!
楼下补充。

18,363

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧