问题描述:
1、首先我使用IdUDP进行通信,我的界面上既有client也有server。
2、UDP包发送的内容是我自己定义的格式,其中有些数据是变长的,为了处理方便我定义了结构体(packed record)来保存打算发送出去的数据,变长部分我使用了动态数组(array of byte)
3、发送的时候没有问题,因为我可以根据内容长度使用setlength给那个动态数组先确定大小。
4、但是接受的时候,我用了相同的packed record结构体作为buff来接受数据,这时候问题出现了,因为我接受之前不知道数据的长度,所以就没有办法给那个动态数组setlength,因此就没有办法接受到那部分数据。我的问题是:
1、我怎么能够预先知道数据体的长度,从而给动态数组指定长度。
2、如果1不可行,那么我能否可以读一次之后,使用独到的结果再给动态数组指定长度,然后接着再读一次buff,我想知道这样可不可行,buff中的值是不是读了一次之后就更新了???
3、有没有人有更好的方法,但是不要告诉我用静态数足,因为我的数据长度的变化范围太大了,不现实。
1、首先我使用IdUDP进行通信,我的界面上既有client也有server。
2、UDP包发送的内容是我自己定义的格式,其中有些数据是变长的,为了处理方便我定义了结构体(packed record)来保存打算发送出去的数据,变长部分我使用了动态数组(array of byte)
3、发送的时候没有问题,因为我可以根据内容长度使用setlength给那个动态数组先确定大小。
4、但是接受的时候,我用了相同的packed record结构体作为buff来接受数据,这时候问题出现了,因为我接受之前不知道数据的长度,所以就没有办法给那个动态数组setlength,因此就没有办法接受到那部分数据。我的问题是:
1、我怎么能够预先知道数据体的长度,从而给动态数组指定长度。
2、如果1不可行,那么我能否可以读一次之后,使用独到的结果再给动态数组指定长度,然后接着再读一次buff,我想知道这样可不可行,buff中的值是不是读了一次之后就更新了???
3、有没有人有更好的方法,但是不要告诉我用静态数足,因为我的数据长度的变化范围太大了,不现实。
解决方案 »
- 请教个问题:ondestroy事件中如果自己写了代码,最后一行一定要加上inherit destroy吗?
- DELPHI 2010竟然不支持函数返回值???
- dbgrideh上画currnecy控件是怎么做的啊
- TIdTcpClient和TIdTcpServer传递XML数据的问题~~!
- 大问题,请高手们帮忙解决,先谢谢
- 打印时,数据不能刷新的问题
- 抓IP包程序,请高手帮忙。。。来者送分。
- 使用olecontainer时,如何在运行时指定 OLE对象?
- 小鱼儿!你好吗?大家好!有关MIDAS的讨论!
- dbgrid中各字段显示问题
- 没有.pas文件,只有dcu 文件,我想引用这个单元里的函数,怎么办?
- 第一次做一个可视控件就遇上困难,等待高手。。。
ms得經典做法:typedef _tagStruct struct
{
int nCmd;
int nLen;
char szData[1];
} DynamicStruct;看到了沒?..
nCmd:integer;
nLength:integer;
szData:Array of char;
end;
接收时,先接收2个整型的size数据,转换成cmd和length,再根据length来动态社定szdata的长度,然后再接收length长度的szData数据。
我的TR的定义如下
-------------------------------
TCommand=packed record
version:byte; //协议版本号
totalPack:byte;//总包数
packNumber:byte;//包序号
equipType:byte; //设备类型
commandNumber:byte;//命令编号
apIp1:byte; //网管接入点ip
apIp2:byte;
apIp3:byte;
apIp4:byte;
equipNumber:byte;//设备编号
answer:byte;//应答标志
commandLength:byte;//命令体长度
commandData:array of byte; //命令数据
//commandData:string;
end;
TR=packed record //数据体定义
head:char; //起始标志单元
crc:word;//crc校验位
Command:TCommand;//命令体
tail:char;//结束标志单元
end;
------------------------------------------------------
接受数据的程序如下
------------------------------------------------------
procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TStream;
ABinding: TIdSocketHandle);
var blockComm,tempComm:TR;
templength:integer;
begin
AData.ReadBuffer(tempComm,AData.Size);
templength:=tempComm.Command.commandLength;
setlength(blockComm.Command.commandData,blockComm.Command.commandLength);
AData.ReadBuffer(blockComm,AData.Size);//这里提示错误.....高手帮我!!!!end;
templength:=tempComm.Command.commandLength;
setlength(blockComm.Command.commandData,blockComm.Command.commandLength);
AData.ReadBuffer(blockComm,AData.Size);//这里提示错误.....高手帮我!!!!///////////////////////////流的指针位置移动了,要移回头,才能正确读出。
AData.Position:=0;//////////////////////////////////////////
AData.ReadBuffer(blockComm,AData.Size);
是不是我发送的有问题,现在将发送的代码也贴出来
-------------------------------------------------------------
procedure TTC10BE1.TransferModeSet(DeviceIP:string;set1,set2,set3,set4:byte);
var blockComm:TR; //TR的格式上面有详细的定义,有没有可能问题出在结构体上???
tempString,tempIP:string;//这两个用来处理IP使他能够分成4字节发送出去
pt:^variant; //发送之前使用CRC校验,需要用到指针
begin
blockComm.head:='X';
blockComm.Command.version:=1;
blockComm.Command.totalPack:=1;
blockComm.Command.packNumber:=1;
blockComm.Command.equipType:=self.DeviceStyle;
blockComm.Command.commandNumber:=30;
//----------------处理IP------------------------------//
tempIP:=self.DeviceIP; //DeviceIP是一个私有成员变量
tempString:=leftStr(tempIP,pos('.',tempIP)-1);
blockComm.Command.apIp1:=StrToInt(tempString); //1
tempIP:=rightStr(tempIP,length(tempIP)-pos('.',tempIP));
tempString:=leftStr(tempIP,Pos('.',tempIP)-1);
blockComm.Command.apIp2:=StrToInt(tempString); //2
tempIP:=rightStr(tempIP,length(tempIP)-pos('.',tempIP));
tempString:=leftStr(tempIP,Pos('.',tempIP)-1);
blockComm.Command.apIp3:=StrToInt(tempString); //3
tempIP:=rightStr(tempIP,length(tempIP)-pos('.',tempIP));
//tempString:=leftStr(DeviceIP,Pos('.',DeviceIP)-1);
blockComm.Command.apIp4:=StrToInt(tempIP); //4
//--------------完毕------------------------------------//
blockComm.Command.equipNumber:=self.DeviceID;
blockComm.Command.answer:=0;
blockComm.Command.commandLength:=6;
setLength(blockComm.Command.commandData,6);
blockComm.Command.commandData[0]:=set1;
blockComm.Command.commandData[1]:=set2;
blockComm.Command.commandData[2]:=set3;
blockComm.Command.commandData[3]:=set4;
blockComm.Command.commandData[4]:=0;
blockComm.Command.commandData[5]:=0;
//-------------CRC校验-------------------------------------//
pt:[email protected];
blockComm.crc:=GetCrc16(pt,sizeof(blockComm.Command));
blockComm.tail:='X';
//--------------发送---------------------------------------//
frmMain.UDPSend.SendBuffer(DeviceIP,RemotePort,blockComm,sizeof(blockComm));//调用主窗口的UDPClient发送数据包
end;
就像 beyondtkl和gzmhero说得那样你要重新修改结构体的结构,加一个长度字段
我现在接受到的数据其他的都可以,就连结尾的Tail的'X'都能接收到
但是唯独commandData没有内容,我现在在想是不是他的数据类型造成的
因为commandData是动态数组如果在结构体当中添加一个length字段有什么好处?
我对这个解决房案的精妙之处不是太了解
是用这个值去判断发送的数据是否全部接受了吗?
----------------------------------------------
额外一句话,今天刚刚看到AD的照片,呵呵,真酷!!!
nCmd:integer;
nLength:integer;
szData:Array of char;
end;
接收时,先接收2个整型的size数据,转换成cmd和length,再根据length来动态社定szdata的长度,然后再接收length长度的szData数据。
-------------------------------------------------------
可以先从AData读取2个证型的size数据吗?是不是这样AData.readbuffer(MyStruct,2);
这个控件我真的是第一次接触,感觉她出的问题都莫名其妙(还是自己了解的不深)
对于AData,Tstream类型的数据,我在想他是不是把每次接受到的数据都按顺序的排在AData里面,那么如果有新数据放进来会发生什么事情哪?这个数据是不是也放到了AData里面拿?如果我第二次触发Onread事件的时候,我再用AData.Position:=0;//////////////////////////////////////////
那么这个时候我读到的本次受到的新数据的开头,还是原来数据的开头那?如果是现在新数据的开头,那么原来的数据拿?被冲掉了吗...
buffersize决定的是什么?如果buffersize设置很小,一个包的数据存不下又会发生什么情况那?
希望大家讨论讨论...
MyStruct=record
nCmd:integer;
nLength:integer;
szData:Array[0..0] of char;
end;
然后先把所有接收的数据写到一个缓冲区buf中,然后通过强制结构变换取得想要的值。
或者就在缓冲区buf中,取指定位置的数据。参见我的回答
http://community.csdn.net/Expert/topic/3824/3824705.xml?temp=.6447412
你给我的帖子里面竟然还有我的回复,呵呵
我说的是:高级话题,不懂...
哈哈哈哈哈...
-------------------------------
TCommand=packed record
version:byte; //协议版本号
totalPack:byte;//总包数
packNumber:byte;//包序号
equipType:byte; //设备类型
commandNumber:byte;//命令编号
apIp1:byte; //网管接入点ip
apIp2:byte;
apIp3:byte;
apIp4:byte;
equipNumber:byte;//设备编号
answer:byte;//应答标志
commandLength:byte;//命令体长度
commandData:array of byte; //命令数据
//commandData:string;
end;
TR=packed record //数据体定义
head:char; //起始标志单元
crc:word;//crc校验位
Command:TCommand;//命令体
tail:char;//结束标志单元
end;
------------------------------------------------------