蓝森林首页 | 返回主页 | 本站地图 | 站内搜索 | 联系信箱 | -->
 您目前的位置:首页 > 自由软件 > 技术交流 > 应用编程 -->


    

蓝森林 http://www.lslnet.com 2006年8月16日 14:08

recvfrom的问题

调用recvfrom()函数(带标志0)去接收10个字节,要是在udp缓冲区中有20个字节,是不是剩余的10个字节被丢掉了?因为我第二次去接收没有了,要是这样的话如何是好?国为我要格式化数据,如何才能使recvfrom不丢掉剩余的10个字节?(MSG—PEEK是不行的,如果这样的话,下次调用recvfrom去接收剩余的10个字节,又是错误的数据了)哪位大虾可以指点一二。



Re: recvfrom的问题

> 调用recvfrom()函数(带标志0)去接收10个字节,要
> 是在udp缓冲区中有20个字节,是不是剩余的10
> 字节被丢掉了?

This is corrent, because your set buffer's size smaller than the datagram's length, so the datagram will be truncated. And, if you use recvmsg() system call, you will find that a new flag "MSG_TRUNC" will be set in messgage flag.

因为我第二次去接收没有了,要是这样的话如何是好?国为我要格式化数据,如何才能使recvfrom不丢掉剩余的10个字节?(MSG—PEEK是不行的,如果这样的话,下次调用recvfrom去接收剩余的10个字节,又是错误的数据了)哪位大虾可以指点一二。

It sounds like you are using a big datagram to contain small pieces of packages, and every package's length is 10 bytes. And, you'd like to get 10 bytes each time and check if it's correct or not.

Is this correct? Please clarify your question.

One quick suggestion is, you may consider to use TCP instead, because TCP is more stream-alink. And, it only truncates urgent data. If you still like UDP, considering set your every datagram's size as a confirmed value, or use some kinds of byte, such as '\n', to mark the end of every message.

EJ
-------------------------
There's no spoon
- The Matrix
-------------------------

谢谢ejiang,正是如此!

应用层的数据包分为三个部分:
header,description infomations ,data
其中header 是10 bytes,description的长度也是固定的(每个包的 description infomation 长度按照协议的规定,我的程序是知道的,不用担心,比如说是10 bytes吧),但是data部分却是可变的,(其长度在description infomation部分有一个说明域datalen).。

如果服务器出了错误,只会发送一个包含10个bytes头的数据包。

对方(服务器,即发送方)在发送这个包的时候是整个的发送,但接收方(即我,客户方)在接收的时候,应先接收10个bytes的header,判断出了错没有,如果没有,才能再去接收description infomation部分的10 bytes,再根据description infomation 的说明域datalen,再去接收datalen 个bytes 的data.

应该来说不应一下就接收完整个数据包,国为可能只接收了,5 bytes ,or 10 bytes,15 bytes 30 bytes etc.不便于分析。

如果第一次使用MSG_PEEK标志接收10 bytes分析,第二次使用MSG_PEEK标志接收10+10=20 byes 分析,第三次使用0标志接收10+10+datalen来分析是可行的.


问题是最开始设计程序的时侯,调用setsockopt(...SO_RCVLOWAT...)设置了 水位,然后调用select()
来判断准备好了没有,问题本应迎刃而解。但程序运行时报告错误,即不能设置水位(使用了无效协议,我用的是udp协议)。所以改用了带有MSG_PEEK标志的recvfrom()调用来判断有没有规定的字节数(比如上面说的10bytes header)到达,然后再去recvfrom()
(带0标志)这10个bytes,读的时候可能又不只10 bytes,
而是10+10+datalen bytes了,因此数据丢了,我现在不想大幅改动程序,我只需要先接收10 bytes,然后10 bytes,然后datalen,但是后面的数据不要给我丢弃就行,怎么办才好,ejiang大侠,及各位高人欢迎指点,
不胜感激。




Re: 谢谢ejiang,正是如此!

Yeah, use MSG_PEEK is a good way, actually your current solution is good enough to overcome your problem. Another way to do so is using a large enough buffer, say 20K, to get the entire datagram with the MSG_WAITALL flag, then focus on the buffer.

EJ
-------------------------
There's no spoon
- The Matrix
-------------------------



Copyright © 1999-2000 LSLNET.COM. All rights reserved. 蓝森林网站 版权所有。 E-mail : webmaster@lslnet.com