recv函数的flags参数设置为MSG_PEEK只能接收第一个包

时间:2021-05-18 23:55:59
Win2000环境下的WinSck编程。

如果recv函数的flags参数设置为MSG_PEEK,则无论len参数是多大,都只能接收第一个包。

比如在发送端先发送"aaa",再发送"bbb",则始终只能接收到"aaa"。

是不是与socket的创建或者connect有关?我没有用WSA***函数,用的都是原始函数。

我的发送端在Unix和Windows下都试过,同样的结果。

有解决问题者不仅奉送100分,另可到下面的帖子拿100分。
http://expert.csdn.net/Expert/topic/1720/1720137.xml?temp=.2730219

16 个解决方案

#1


补充说明,我已经“呼叫”过WSAStartup函数了。

#2


如果recv函数的flags参数设置为MSG_PEEK,则无论len参数是多大,都只能接收第一个包。

try it:

flags = 0;

it do work.

#3


是你标志位的设置问题.

#4


http://www.csdn.net/develop/read_article.asp?id=16605

#5


MSG_PEEK   Peek at the incoming data. The data is copied into the buffer but is not removed from the input queue.
也就是说,你没有清空recv buffer, 下次的Onrecieved事件是不会有的。
请不要用MSG_PEEK,除非你有一个thread,去清空这个recv的buf,
最好用flag = 0,来忽略。

#6


首先申明我的目的:我只是想从套接口中取出东西看看,不想删除,这正是MSG_PEEK的作用。

其次,两端程序建立连接后的工作过程:
1. 发送者发送"aaa";
2. 发送者发送"bbb";
3. 接收者以peek方式接收,接收到"aaa";
4. 接受者以peek方式接收,接收到"aaa"。

在这里我是故意造成两次接收相同内容这个效果的。


我的问题是:

为什么只能接收到"aaa",无法接收到后面的"bbb"???????????

#7


但你总要有一个thread去清空呀

#8


再列举一种情况:
1. 发送者发送"1234567890"
2. 发送者发送"abcdefg"
3. 接收者不用peek而直接接收5个字节,收到"12345";
4. 接收者以peek方式接收4096字节,收到"67890"。

步骤4只收到了第一次发送的5个字节以后的内容,没收到第二次发送的内容,可见Windows在这里是分包处理。
有没有办法让步骤4接收到第二次发送的内容呢?

#9


peek的时候是取出数据,但是不清空接收缓冲区的
比如收到了50字节的数据
用peek来读出来,那么数据在接受缓冲区里面还是存在的。
如果用正常方式那么就会把你接收的数据从接收缓冲区里面去掉了

MSG_PEEK   Peek at the incoming data. The data is copied into the buffer but is not removed from the input queue.

lyghe(TComponent* AOwner) 的情况是这样的
再列举一种情况:
1. 发送者发送"1234567890"
2. 发送者发送"abcdefg"
3. 接收者不用peek而直接接收5个字节,收到"12345";
这个时候原来接收缓冲区里面的数据"1234567890"已经变成了"67890";所以下面再接收一定是从6开始的,如果在这一步用peek方式接收的话,那么接收缓冲区的数据还是"1234567890",下面再接收的话还能读出来相同的内容("1234567890")。
4. 接收者以peek方式接收4096字节,收到"67890"。

#10


我受不了了!!!!!

你们说的道理我都明白!

我的问题是既然发送者连续发送了"1234567890"和"abcdefg",为什么peek方式的接收者接收到的只有"1234567890"的内容?为什么后面没有跟上"abcdefg"?

#11


我反复作了实验,只要接收者不把缓冲区中的第一次发送的内容取走,哪怕只剩一个字节在缓冲区中,peek方式都无法读取以后发送的内容。

#12


你真的明白?

#13


peek是什么意思,它只是偷看,查看的意思,就是说你如果不清缓存的话,后面的包内容是peek不到的,除非有PEEK_ALL一样的参数。

#14


你们这么说我倒不明白了,同样的程序在Unix上很正常,在Win上面反而不行。

你们的意思是不是说Windows处理TCP包时是一个一个处理的?前面一个包不处理完就不处理后面的?为什么recv函数不用peek方式能够一次全取出来而用peek就不行?两种方式的内核处理方法不同吗?Microsoft为什么这么傻呢?

#15


痛苦啊

#16


把flag设置为0看看!!

#1


补充说明,我已经“呼叫”过WSAStartup函数了。

#2


如果recv函数的flags参数设置为MSG_PEEK,则无论len参数是多大,都只能接收第一个包。

try it:

flags = 0;

it do work.

#3


是你标志位的设置问题.

#4


http://www.csdn.net/develop/read_article.asp?id=16605

#5


MSG_PEEK   Peek at the incoming data. The data is copied into the buffer but is not removed from the input queue.
也就是说,你没有清空recv buffer, 下次的Onrecieved事件是不会有的。
请不要用MSG_PEEK,除非你有一个thread,去清空这个recv的buf,
最好用flag = 0,来忽略。

#6


首先申明我的目的:我只是想从套接口中取出东西看看,不想删除,这正是MSG_PEEK的作用。

其次,两端程序建立连接后的工作过程:
1. 发送者发送"aaa";
2. 发送者发送"bbb";
3. 接收者以peek方式接收,接收到"aaa";
4. 接受者以peek方式接收,接收到"aaa"。

在这里我是故意造成两次接收相同内容这个效果的。


我的问题是:

为什么只能接收到"aaa",无法接收到后面的"bbb"???????????

#7


但你总要有一个thread去清空呀

#8


再列举一种情况:
1. 发送者发送"1234567890"
2. 发送者发送"abcdefg"
3. 接收者不用peek而直接接收5个字节,收到"12345";
4. 接收者以peek方式接收4096字节,收到"67890"。

步骤4只收到了第一次发送的5个字节以后的内容,没收到第二次发送的内容,可见Windows在这里是分包处理。
有没有办法让步骤4接收到第二次发送的内容呢?

#9


peek的时候是取出数据,但是不清空接收缓冲区的
比如收到了50字节的数据
用peek来读出来,那么数据在接受缓冲区里面还是存在的。
如果用正常方式那么就会把你接收的数据从接收缓冲区里面去掉了

MSG_PEEK   Peek at the incoming data. The data is copied into the buffer but is not removed from the input queue.

lyghe(TComponent* AOwner) 的情况是这样的
再列举一种情况:
1. 发送者发送"1234567890"
2. 发送者发送"abcdefg"
3. 接收者不用peek而直接接收5个字节,收到"12345";
这个时候原来接收缓冲区里面的数据"1234567890"已经变成了"67890";所以下面再接收一定是从6开始的,如果在这一步用peek方式接收的话,那么接收缓冲区的数据还是"1234567890",下面再接收的话还能读出来相同的内容("1234567890")。
4. 接收者以peek方式接收4096字节,收到"67890"。

#10


我受不了了!!!!!

你们说的道理我都明白!

我的问题是既然发送者连续发送了"1234567890"和"abcdefg",为什么peek方式的接收者接收到的只有"1234567890"的内容?为什么后面没有跟上"abcdefg"?

#11


我反复作了实验,只要接收者不把缓冲区中的第一次发送的内容取走,哪怕只剩一个字节在缓冲区中,peek方式都无法读取以后发送的内容。

#12


你真的明白?

#13


peek是什么意思,它只是偷看,查看的意思,就是说你如果不清缓存的话,后面的包内容是peek不到的,除非有PEEK_ALL一样的参数。

#14


你们这么说我倒不明白了,同样的程序在Unix上很正常,在Win上面反而不行。

你们的意思是不是说Windows处理TCP包时是一个一个处理的?前面一个包不处理完就不处理后面的?为什么recv函数不用peek方式能够一次全取出来而用peek就不行?两种方式的内核处理方法不同吗?Microsoft为什么这么傻呢?

#15


痛苦啊

#16


把flag设置为0看看!!