用socket发送记录型数据,接收端该如何读取?(100分)

  • 主题发起人 主题发起人 星空
  • 开始时间 开始时间

星空

Unregistered / Unconfirmed
GUEST, unregistred user!
在客户端定义了如下记录:
GoodsRec=record
id:integer;
goodsid:string[7];
goodsname:string[50];
goodsnum:integer;
goodsunit:string[10];
goodsprice:currency;
goodstotal:single;
end;
EmpMessage=record
ename:string[12];
phone:string[20];
address:string[100];
sendtime:string[30];
memberid:string[9];
orderid:string[13];
computerid:string[8];
MerkId:string[2];
cardid:string[2];
mem:string[255];
ReCount:integer;
G_Record:array of GoodsRec;
end;

然后用clientsocket.sendbuf发送,用serversocket.receivebuf接收,

仅读出了除G_Record外的数据,G_Record中的数据该如何读取?
 
我曾做过类似的程序,解决方法是用按位读取,如:
user_type:=integer(buf^);
inc(integer(buf),4);
for i:=1 to 12 do
begin
pin:=pin+char(buf^);
inc(integer(buf),1);
end;
听说有一个API函数copymemory可以更方便的使用,但我不会,如果谁会顺便告诉我。
 
由于EmpMessage中的G_Record实际上一个GoodsRec的指针,所以你
SendBuf的时候只是把他的指针发过去了,所以接收不到。
解决的办法是:
创建一个临时缓冲区,然后用CopyMemory将EmpMessage拷贝到临时缓冲区中,
接着用一个循环(循环的次数由你的G_Record中GoodsRec的个数来决定)将
G_Record中GoodsRec挨个拷贝到临时缓冲区中(注意:追加在EmpMessage之后),
然后再将这个临时缓冲区用SendBuf发过去,接收端收到后先将Buffer中的EmpMessage
取出来,然后SetLength(G_Record,GoodsRec的个数),如果我没有猜错的话ReCount
应该是GoodsRec的个数。最后也是用一个循环从
Pointer(DWORD(Buffer)+SizeOf(EmpMessage))处开始拷贝数据到GoodsRec[Index]中,
每次拷SizeOf(GoodsRec)个字节。

 
对指针操作不熟,请问该如何将GoodsRec追加到EmpMessage后呢?
 
问题基本解决,只是不能将GoodsRec包含在EmpMessage里,不然在接收到后不能用setlength

设置G_Record的大小(我想这应该是可以的,但我不知该怎么处理了)。
 
还有个问题,当GoodsRec比较大时,接收到的内容不对。是否得分块发送,接收后再拼装?

这样一来,不就得把缓冲区的大小先发?再说拼装有什么好的方法。请高手们指教!
 
解决方法很简单 不过写得很辛苦,,要给分哦~~~

改一改 EmpMessage 结构 ,加上 GRECORDCOUNT :BYTE 一项

EmpMessage=record
ename:string[12];
phone:string[20];
address:string[100];
sendtime:string[30];
memberid:string[9];
orderid:string[13];
computerid:string[8];
MerkId:string[2];
cardid:string[2];
mem:string[255];
ReCount:integer;
G_Record:array of GoodsRec,
加上 GRECORDCOUNT :BYTE; //指定array of GoodsRec 的大小
-----------------------------------
发送时:
procedure sendrecord;
var
sendem :EmpMessage;
grecorcount:Byte;
recordsize:integer;
SendStream :tmemorystream;
begin
grecorcount:=3;
Setlength(sendem.G_record,grecorcount);
recordsize:=sizeof(EmpMessage) +grecorcount*sizeof(GoodsRec);//注意这里!!
sendem.grecorcount:=grecorcount;
sendem.ename:='test';
......//填完其他的数据
sendem.G_record[0].goodsid:='aaaaaaaaaa';
sendem.G_record[0].goodsname:='bbbbbbbbb';
......
sendem.G_record[grecorcount].goodsid:='fffffff';
sendem.G_record[grecorcount].goodsname:='zzzzzzzz';

SendStream:=Tmemorystream.create;
try
Sendstream.write(sendem,recordsize);
Sendstream.position:=0;
clientsocket.sendStream(sendstream);
finally
Sendstream.free;
end;
end;

接收端

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
type PEmpMessage=^EmpMessage;
var
EM:EmpMessage;
buf:pchar;
grecordcount:integer;
begin
getmem(buf,socket.ReceiveLength);
try
 socket.ReceiveBuf(buf^,socket.ReceiveLength);
 EM:=PEmpMessage(buf)^;
 grecordcount:=em.grecordcount;

////取出 G_record 数据 ///其他数据省略不写了
memo1.lines.add(inttostr(EM.G_Record[0].id));
memo1.lines.add(EM.G_Record[0].goodsid);
memo1.lines.add(EM.G_Record[0].goodsname);
........
finally
freemem(buf);
end;

以上已经测试通过,有问题可以联系我 kenysm@21cn.com
 
最简单的方法:
定义
var
sendrec :EmpMessage;
recvrec :EmpMessage;
//在此填写send的内容;
发送时:ClientSocket1.Socket.SendBuf(sendrec,sizeof(sendrec));
接收时:Socket.ReceiveBuf(recvrec,socket.ReceiveLength)));
此时就可以直接读取recvrec里的数据了,如:memo1.lines.add(inttostr(recvrec.G_Record[0].id));
 
不好意思,很久没来,忘了结束问题。谢谢各位了。
 
后退
顶部