程序中继承的CSocket
长连接 TCP协议
不定长包 3个字节 2个字节 4个字节 6个字节的都有char *buff=new char[32];
memset(buff,0,sizeof(buff));
MySock.Receive(buff,sizeof(buff));接收完后,跟踪程序,发现buff 的数据为 0x004a14c0 "s屯屯屯屯"
前半部分 "s" 是正常接收到的数据。
后面的"屯屯屯屯"是怎么回事呢?
运行抓包软件发现包的发送是正常的,但很多包粘在一起了。
但是Receive接收到的却是上面那样的数据。真是奇怪啊!
长连接 TCP协议
不定长包 3个字节 2个字节 4个字节 6个字节的都有char *buff=new char[32];
memset(buff,0,sizeof(buff));
MySock.Receive(buff,sizeof(buff));接收完后,跟踪程序,发现buff 的数据为 0x004a14c0 "s屯屯屯屯"
前半部分 "s" 是正常接收到的数据。
后面的"屯屯屯屯"是怎么回事呢?
运行抓包软件发现包的发送是正常的,但很多包粘在一起了。
但是Receive接收到的却是上面那样的数据。真是奇怪啊!
而在VC++的QuickWatch里调试跟踪的时候发现buff里收到的包却都是单个的,但有些包不完整(如:只有一个包头),而且接收到的数据有部分是上面所说的情况:0x004a14c0 "s屯屯屯屯" 收到了一些垃圾数据!而并不见粘在一起的包。把接收缓冲区开大一些如 char *buff=new char[256];
跟踪调试时可以看到buff里这样的数据:"s屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯s屯屯屯屯"
我抓包看到的数据都是正常的啊!
接收端接收前也清空了接收缓冲区的(如上面的代码)
不知道那些"屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯"是怎么收到的。请PiggyXP指教。
这样接收吗?MySock.Receive(buff,buff[1]);
我这样试了。接收不到数据。
而且这样也不能解决粘包的问题啊!
况且接收时还要收到"屯屯屯屯屯屯屯屯屯屯屯"的垃圾数据。明天就要交客户了!我完了…………******************************************************8
下面是我查的关于粘包问题的资料TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。
出现粘包现象的原因是多方面的,它既可能由发送方造成,也可能由接收方造成。发送方引起的粘包是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通常TCP会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据。接收方引起的粘包是由于接收方用户进程不及时接收数据,从而导致粘包现象。这是因为接收方先把收到的数据放在系统接收缓冲区,用户进程从该缓冲区取数据,若下一包数据到达时前一包数据尚未被用户进程取走,则下一包数据放到系统接收缓冲区时就接到前一包数据之后,而用户进程根据预先设定的缓冲区大小从系统接收缓冲区取数据,这样就一次取到了多包数据。
粘包情况有两种,一种是粘在一起的包都是完整的数据包,另一种情况是粘在一起的包有不完整的包。
int buflen = sizeof(buf);
send(buflen, 4);
send(buf, buflen);
即先发送缓冲长度,再发送缓冲的数据。在接收方先接收长度
int buflen;
recv(&buflen, 4);
得到长度后再接收真正的数据
recv(buf, buflen);呵呵,其实 PiggyXP 都说了,我只是补充而已 ^_^
/*****************************
int len=0;
char tempbuf[2];//第0个bytes为包的种类,第1个bytes为包的长度
memset(tempbuf,0,sizeof(tempbuf));
MySock.Receive(tempbuf,sizeof(tempbuf));
len=tempbuf[1];//获得包的长度
char *buff=new char[len];//按照长度分配空间
memset(buff,0,sizeof(buff));
MySock.Receive(buff,sizeof(buff));
****************************************/
跟踪调试发现由于tempbuf第一次接收把包的前半部分接收了,buff只接收到了包的后半部分。
len能正确获得包的长度。
我把tempbuf的数据和buff的数据连接起来发现与接收的数据不正确。
有,没有办法让tempbuf接收后数据仍然在缓冲区里。
然后用buff就能正确接收
tempbuf接收到的数据 "w烫"
buff接收到的数据""
连接起来就是 "w烫"而正确的应该是 "w"如果按下面的代码来接收在通信数据量小时可以得到正确结果
char *buff=new char[32];
memset(buff,0sizeof(Buff));
MySock.Receive(buff,sizeof(buff));
但是如果Socket数据量大时就会有上面的问题。郁闷啊!!
这句话有问题,你的意思本来是想将buff指向的32byte的位置全部置0,但是由于buff是个指针变量,所以sizeof(Buff)的值是4(一个指针变量的大小),所以你实际上只将buff指向的4byte的位置置为了0,而4byte之后的值这时仍为未知的,也就是你所看到的“屯”。你改为strlen就应该对了
memset(buff,0,sizeof(buff)) 没有任何问题,这是完全正确的。
int len=0;
char tempbuf[2];//第0个bytes为包的种类,第1个bytes为包的长度
memset(tempbuf,0,sizeof(tempbuf));
MySock.Receive(tempbuf,sizeof(tempbuf));
len=tempbuf[1];//获得包的长度
char *buff=new char[len];//按照长度分配空间
memset(buff,0,sizeof(buff));
MySock.Receive(buff,sizeof(buff));
****************************************/既然已经知道了包的长度len,那在最后俩行程序中直接用len代替sizeof(buff)
这样行不行呢?
楼主为什么要这样呢?
memset(buff,0,sizeof(buff));
MySock.Receive(buff,sizeof(buff));直接这样不就完了末?memset(buff,0,len);
MySock.Receive(buff,len);但是因为你的发送端代码不能修改了
那就只能你自己手动把两部分拼接起来了呵呵buff只能收到后半部分了^_^
memset(buff,0,sizeof(buff)) 真的没有问题吗?那么请你运行下面程序段进行试验:
char *buff=new char[32];
// memset(buff,0,sizeof(buff));
printf("%d\n",sizeof(buff));我使用vc6.0编译运行,打印出来的结果是4,而不是32。除非你原本就只是想将4个字节置0而不是32字节,否则这里就有问题。