C++Builder 程序员博客
29 Jul
我用TServerSocket的TCP SOCKET堵塞模式,多线程与四个客户端通信,四个客户端会每隔一秒向我发送数据帧,数据帧的分割采用数据帧头upTransmitterSecondData和数据帧尾END进行分割,现在有一个奇怪的想象,平均每隔二到三天,接收到的数据包会出错一次,随后就正常。下面是出错包的内容:
upTransmitterSecondData ¦523304 ¦2008-06-02 23:51:03 ¦1 ¦35 ¦000F05C20//20 ¦0.40 ¦95.00 ¦10.00 ¦18.20 ¦0.56 ¦630.00 ¦464.00 ¦3.79 ¦40.00 ¦8.30 ¦640.00 ¦759.00 ¦13.30 ¦297.00 ¦0.56 ¦1.63 ¦0.00 ¦0.00 ¦13675 ¦1.13 ¦EN蘵pTransmitterSecondData ¦523304 ¦2008-06-02 23:51:04 ¦1 ¦35 ¦000F05C20//20 ¦0.40 ¦95.00 ¦10.00 ¦18.20 ¦0.56 ¦630.00 ¦464.00 ¦3.79 ¦40.00 ¦8.30 ¦640.00 ¦759.00 ¦13.30 ¦297.00 ¦0.56 ¦1.63 ¦0.00 ¦0.00 ¦13675 ¦1.13 ¦END
正确的是:
upTransmitterSecondData ¦523304 ¦2008-06-02 23:51:03 ¦1 ¦35 ¦000F05C20//20 ¦0.40 ¦95.00 ¦10.00 ¦18.20 ¦0.56 ¦630.00 ¦464.00 ¦3.79 ¦40.00 ¦8.30 ¦640.00 ¦759.00 ¦13.30 ¦297.00 ¦0.56 ¦1.63 ¦0.00 ¦0.00 ¦13675 ¦1.13 ¦ENDupTransmitterSecondData ¦523304 ¦2008-06-02 23:51:04 ¦1 ¦35 ¦000F05C20//20 ¦0.40 ¦95.00 ¦10.00 ¦18.20 ¦0.56 ¦630.00 ¦464.00 ¦3.79 ¦40.00 ¦8.30 ¦640.00 ¦759.00 ¦13.30 ¦297.00 ¦0.56 ¦1.63 ¦0.00 ¦0.00 ¦13675 ¦1.13 ¦END
也就是说第一个数据帧尾END被改变了。它不是每次发送数据包都出错,就是大概二到三天,出错一次,请教大家是何原因?
你的程序有没有验证机制,比如说包大小之类的校验一下,如果是错包,重发就是!
我没有采用原始的SCOKET协议进行分装,而是采用TServerSocket的TCP SOCKET堵塞模式,buffer大小为4096,每次接收完数据后进行数据帧分割,然后就会调用memset函数将buffer置零.现在问题是TCP通信情况下,数据帧已经不会出错了,为何还会出错呢?
我认为这就不可能出错的,不是出错重发问题啊!
因为TCP底层已经进行数据校验,保证数据的正确性,我的程序采用TServerSocket的TCP SOCKET堵塞模式,并非直接从底层SCOKET协议编程,所以可以认为接收到的数据已经正确了,如果说我的程序代码出错,为何平时代码不错呢?
这应该跟传输没关系,是应用层给TCP的数据出了问题,像“EN蘵”这样的情况我感觉是你对填充数据的缓存没处理干净。
memset函数怎么用的呢?看样子是指针错误,非法的内存块。
用什么版本的 SINFF ?
有时候 对的版本也会出现这种情况。。。
不一点是你代码错了
如果真的话 判断一下 发过来包的长度
然后和你需要接受的做比较
如果不一样 推出 重新 发送邀请命令
再接受。 成功了再做你需要的事情
最好祝你好运气。
MABEY TServerSocket 9.0 以下的版本存在BUG
建议升级道 10.0
当然老版本 代码不要该
你找台 没用的机器 装上 10.0 然后做测试。。
有时候 错的版本也会出现这种情况。。
不一定是你代码错了
然后和你需要接受数据大小做比较
我的编程环境是CB6+UPDATE4,分别和JAVA、VC和CB三种程序的客户端通信,奇怪的是与JAVA、VC的客户端通信均正常,就是与另外一家公司用CB6做客户端通讯出现这个问题!
memset(buffer, 0, 4096); // initialize the buffer
//////////////////////接收数据
if(pStream->WaitForData(1000))
{
ReadByteNum=pStream->Read(buffer, 4096);
if(ReadByteNum <= 0)
{
//缓冲区无数据
count++;
if(count>6)
TimeOut=true;
}
else
{
//有数据读入
netData="";
for(i=0;i <ReadByteNum;i++)
{
netData=netData+buffer[i];
}
//判断是否有错误的数据帧
if(!JudgeIsCorrectChar(netData))
{
netData="";
switch(equipmentID)
{
case 1: OtherTX1String=""; break;
case 2: OtherTX2String=""; break;
case 3: OtherTX3String=""; break;
case 4: OtherTX4String=""; break;
case 5: OtherTX5String=""; break;
case 6: OtherTX6String=""; break;
case 20: OtherANTString=""; break;
default:{}
}
/*
EnterCriticalSection(&OPLogInfoQLock);
AddInfoToQueue(LogInfoQueue,DateTimeToStr(Now())+" "+IntToStr(ReadByteNum)+" @"+netData+"@",-1);
LeaveCriticalSection(&OPLogInfoQLock);
*/
}
else
ReceiveDataHandle(equipmentID,netData);
count=0;
}
}
10楼的接收代码谁写的?ReadByteNum=pStream->Read(buffer, 4096); 如果这个只读取到了10个字节,数据会如何处理?
很明显应该是发送端或者接收端没有处理好最后一个字符。
EN蘵pTransmitterSecondData 即 EN\xccupTransmitterSecondData
感觉这段程序没什么问题啊。。。
难道C++builder的bug???
在错误的数据帧中,不仅仅是数据帧的结尾会出错,在数据帧的中间也会出错,如:
upTransmitterSecondData ¦523304 ¦2008-07-14 18啜 ? .00 ¦471.00 ¦3.79 ¦40.00 ¦8.30 ¦640.00 ¦760.00 ¦13.5 ¦296.00 ¦0.46 ¦1.75 ¦0.00 ¦0.00 ¦9540 ¦1.20 ¦END,这就和处理最后一个字符没有太大关系了,顺便提一下,对方用的是TServerSocket的非堵塞模式,而我用的是TServerSocket的堵塞模式,而另外两家用JAVA和VC的程序客户端均用的堵塞模式与我通信的,与这两家通信就没有任何问题,数据帧不会出错,就是与用CB这家通信时,数据帧出错!很是奇怪?难道与通信模式有关吗?
netData=""; for(i=0;i <ReadByteNum;i++) { netData=netData+buffer[i]; }
象这样子的代码,改成下面的代码不是更简洁而且更具效率?
netData.SetLength(ReadByteNum); memcpy(netData.c_str(), buffer, ReadByteNum);
会不会是CB6.0 TClientSocket的非堵塞模式有BUG,记得五、六年前刚接触TServerSocket时,曾做过一个C/S程序,客户端和服务端两边分别用是TServerSocket和TClientSocket的非堵塞模式进行通信,而且两边通信的数据量非常小,只有几十个字节(为了同步时间),每隔几秒发送一次。当程序运行在数据吞吐量比较小的网络中,程序不会报错,当网络吞吐量比较大时(类似网吧),程序就会出错,当时一直没有在意,现在又出现这种现象,会不会是TClientSocket的非堵塞模式有BUG呢?
15楼:netData=(AnsiString)buffer; 岂不更简洁?我现在着急找到原因啊!
象这种情况,原因应该从对方的代码当中找。
网络拥塞时会出错的
去搞份别人成功的代码
看懂了发展一下
不就行了啊
原因找到了:和程序没有任何关系,是瑞星杀毒软件造成的,我把瑞星杀毒软件退出运行了一个多星期,网络错包再也没有出现,这和我之前看到的一篇帖子不谋而合,那篇帖子说的是卡巴斯基会造成网络通信帧错误,这次是瑞星,真的很奇怪,但的确是这样的。我要给瑞星打个电话问问!