为什么收到FD_READ消息了,却读不到数据?

screen12 2016-05-31 04:51:49
我用的是TCP协议,非阻塞方式。客户端向服务端发送一个数据包,服务端的一个窗口会收到FD_READ消息,然后我用recv把数据收了。一切正确。

可是问题就在于:服务端数据收完以后(长度也和客户端发送的一样),却马上又收到一个FD_READ消息,而此时客户端并没有发送任何数据。

我用select检测了一个,居然结果还是:这个套接字,是可读的。但是用recv来收数据,却返回Socket_error,然后调用WSAGetlasterror(),返回WSAEWOULDBLOCK,这意味着,接收缓冲区无数据可收。

真是奇怪,客户端只发一个数据包,服务端也收了这个数据包,一切正确。可是服务端收完这个数据包以后,却又收到一个FD_READ消息,而客户端并没有。而且用select来检测,发现它是可读的。而真正收的话,又收不到数据,显示接收缓冲区空。

这是怎么回事?
...全文
373 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
叶恭介叶恭介 2016-06-04
  • 打赏
  • 举报
回复
引用 6 楼 screen12 的回复:
[quote=引用 5 楼 cvbtvbwu 的回复:] 首先看你的问题,觉得不解决先好,因为我看到这句“我的程序是:每次有数据来的时候,都要至少收一个头部大小(12字节),收不到不罢休,循环收”,就觉得这句话产生的问题更严重(这有可能导致你写的问题),为什么一定要这么做了,你可以收到数据缓存起来,再根据接收到的数据进行分析处理,不要在Select里循环,还非阻塞这么
这样不好?我的服务端,每当有FD_READ消息时,就意味着有新的数据包来了。我先用recv收一个头部,再根据头部找到后面的数据包长度,再收后面的数据包。如果收的字节不够,就在循环里转,直到收满需要的字节数为止。 这样,好象是把套接字设为阻塞方式了,是吧?本来,把消息绑定到窗口上,就是把套接字设为非阻塞方式。可是我用程序,好象又把它设为阻塞方式了。好象这样是不好。 可是,我的服务端程序,所有套按字,是把消息绑定到同一个窗口上的。也是在同一个线程中完成的。所以,一个FD_READ消息来的时候,必须处理完,不能收了一部分数据,放那里再去处理别的消息。因为所有套按字共用一个线程,以及一个数据接收缓冲区。 [/quote] "因为所有套按字共用一个线程,以及一个数据接收缓冲区。",为每个SOCKET创建自己的数据缓冲区,就算所有套接字用同一个线程,用一个数据接收缓冲区,你FD_RECV时,判断是哪个SOCKET,存入SOCKET的自己数据缓冲区就行了
叶恭介叶恭介 2016-06-03
  • 打赏
  • 举报
回复
首先看你的问题,觉得不解决先好,因为我看到这句“我的程序是:每次有数据来的时候,都要至少收一个头部大小(12字节),收不到不罢休,循环收”,就觉得这句话产生的问题更严重(这有可能导致你写的问题),为什么一定要这么做了,你可以收到数据缓存起来,再根据接收到的数据进行分析处理,不要在Select里循环,还非阻塞这么
_船长_ 2016-06-03
  • 打赏
  • 举报
回复
screen12 2016-06-03
  • 打赏
  • 举报
回复
引用 5 楼 cvbtvbwu 的回复:
首先看你的问题,觉得不解决先好,因为我看到这句“我的程序是:每次有数据来的时候,都要至少收一个头部大小(12字节),收不到不罢休,循环收”,就觉得这句话产生的问题更严重(这有可能导致你写的问题),为什么一定要这么做了,你可以收到数据缓存起来,再根据接收到的数据进行分析处理,不要在Select里循环,还非阻塞这么
这样不好?我的服务端,每当有FD_READ消息时,就意味着有新的数据包来了。我先用recv收一个头部,再根据头部找到后面的数据包长度,再收后面的数据包。如果收的字节不够,就在循环里转,直到收满需要的字节数为止。 这样,好象是把套接字设为阻塞方式了,是吧?本来,把消息绑定到窗口上,就是把套接字设为非阻塞方式。可是我用程序,好象又把它设为阻塞方式了。好象这样是不好。 可是,我的服务端程序,所有套按字,是把消息绑定到同一个窗口上的。也是在同一个线程中完成的。所以,一个FD_READ消息来的时候,必须处理完,不能收了一部分数据,放那里再去处理别的消息。因为所有套按字共用一个线程,以及一个数据接收缓冲区。
screen12 2016-05-31
  • 打赏
  • 举报
回复
刚才试了一下,如果把这个第二个不该有的FD_READ消息抛弃,直接return 0返回。则程序一切正确。
screen12 2016-05-31
  • 打赏
  • 举报
回复
引用 1 楼 VisualEleven 的回复:
是这种情况吗? Consider the following sequence: 1. Network transport stack receives 100 bytes of data on socket s and causes Windows Sockets 2 to post an FD_READ message. 2. The application issues recv( s, buffptr, 50, 0) to read 50 bytes. 3. Another FD_READ message is posted because there is still data to be read.
好象不是这种情况。这种情况是说,发来100字节的数据,程序收了50,处理结束后返回,由于还有数据没取完,因为系统又发了一个FD_READ消息。 我的情况是:客户端发了16个字节的数据过来,服务端先收12字节(头部的大小是12),然后再把剩下4个字节收完。应该是数据取完了。 而且,第二个FD_READ消息来的时候,用select检测,有数据,说这个套接字可读。但是用recv去读,却读不出数据。这也进一步表明,数据取完了。 我的这个问题就好象是:客户端发来一个数据包,服务端一下子收到两个FD_READ消息,在第一个消息里,已经把数据取完了,接着处理第二个消息时,已经无数据可取了。于是就停在循环里(我的程序是:每次有数据来的时候,都要至少收一个头部大小(12字节),收不到不罢休,循环收)。 可我看书上说,如果第一个FD_READ没有处理的时候,再来数据,不会发第二个FD_READ消息。而且事实上也没有新的数据到来。但是select却检测这个套接字可读。真是奇怪! 我的程序就这样在那个循环里转,然后客户端发数据时,它一下子收到数据了,就可以循环里出来了。但是这毕竟造成了程序逻辑的错误。
Eleven 2016-05-31
  • 打赏
  • 举报
回复
是这种情况吗? Consider the following sequence: 1. Network transport stack receives 100 bytes of data on socket s and causes Windows Sockets 2 to post an FD_READ message. 2. The application issues recv( s, buffptr, 50, 0) to read 50 bytes. 3. Another FD_READ message is posted because there is still data to be read.

18,356

社区成员

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

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