带指针字段的结构发送问题(100分)

  • 主题发起人 主题发起人 xiao_min
  • 开始时间 开始时间
X

xiao_min

Unregistered / Unconfirmed
GUEST, unregistred user!
TBindConnect=packed record
Head:THeader;
System_id:pchar; //max:16
Password:pchar; //max:9
System_type:pchar; //max:13
Interface_version:byte;
Ton:byte;
npi:byte;
Address_range:byte;
end;
其中:
  THeader结构中是几个Integer
问题:
  那几个pchar类型的字段,发出去的都是地址,而不是内容,
请问:
  有可能通过Socket.Senbbuf直接将一个TBindConnect类型的变量的所有内容发送出去么?

  
 

System_id:pchar; //max:16
Password:pchar; //max:9
System_type:pchar; //max:13

换成

System_id: array[0..15] of pchar; //max:16
Password: array[0..8] of pchar; //max:9
System_type: array[0..12] of pchar; //max:13

试一下
 
发送的时候,不要用两个指针变量的直接赋值,而是把内容赋值给这个指针的指向.
我解决过这样的问题
 
当然是可以的了
 
试试MilkRoad的方法吧
我也没有做过这样的应用
 
to xianjun:
  不管如何,多谢!!
 
to MilkRoad:
  那样当然可以,不过不合我的要求,如果是静态数组,每次发送的数据都是一样长的,
而我的那个串每次长度不定
  本来应该是123#0的,会发出去123#0#0#0#0....
  这样对方取我的数据可能会出问题(是已经存在的系统,不是我做的,:))
to melissa:
  我个应该不是问题,我跟踪程序,到发送之前,结构里面的数据都是正确的
  你不妨新开一个工程:
  试试这个:
test=packed record
a:integer;
b:pchar;
end;

procedure TForm1.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
var
t:test;
begin
getmem(t.b,10);
t.a:=01;
strpcopy(t.b,'1234567890');
socket.SendBuf(t,14);
freemem(t.b);
end;
  收不到正确的数据。。。

to 陈锡震:
  当然可以?请说出方法。。
 
1、如果用静态数组来存放要发送的字符串,就不会有问题,编程也比较方便,但这样比较
浪费存储空间。如果有压缩机制的话,可以用压缩来处理。
2、如果一定要用String或PChar类型的话,我想到的办法就是进行分步发送校验方式(我自己
想出来的词^_^),就是把发送和接收分为两次进行,第一次收发文件包信息,其中用一些
变量标识字符串的长度,哪个字符串从哪里开始,有多长;第二次收发数据正文,并根据
文件包的信息来进行分解。这样会给编程带来很大的麻烦——但这些麻烦也不一定是坏事。
 
to xiaomin:
那就把结构里的数组定义成动态的
然后,用setlength给TBindConnect。System_id设置长度
试试,我也没试验
:(
 
to Sachow:
1、不是浪费不浪费空间的问题,而这用静态数组发过去的数据,对方会不认识(那
个系统早已经在跑了)
 2、同上,协议是早已定了的,不可能由我一个客户端来改它

  我现在是把数据再写到流中去,然后发送流,但这样一来,定义这些结构根本没
有什么意义了(有一大堆的结构),而且那样的话,程序结构不如用结构来存储看得
爽,:)
 
to coolbaby:
早已经试过了,不然我就不会来问了
 动态数组,pchar都不行,只有试了静态数组可以,但发出去的格式又不对
 
你应该早说你的程序要挂入别的系统中嘛,这样回答的人就不会把它当作一个常规的实现来
回答了。
用流发不是很好吗,省了你很多事。
但是最终应该了解对方系统是怎么接收的。首先,如果发过去的数据只是存在一个结构中一
次性发送,而不是像我前面想的那样分次发送的,那么每次发送和接收的数据一定是定长的!
否则对方该怎么分解收到的结构中的各个成员呢?在此必须清楚的是发送出去的数据在空间
上的连续存储的,所以不应该存在格式不对的问题。有可能是数组定义得不够长。例如其中
System_id成员,最大长度是16,你应该定义一个有17维的数组,因为在C中字符串是以'/0'
为结束的,PChar就是以'/0'结束的,所以应该留出存放结束符的这一个字节的空间。你试
试看。
如果不是这样的话,就要看结构中的THeader类型的成员是怎么定义的了,那可能是一个重要
的组成部分。
 
to Sachow:
  也许是我表达不清楚吧。。。。
不过:
  “有可能通过Socket.Senbbuf直接将一个TBindConnect类型的变量的所有内容发送出去么?”
似乎已经够明白了吧。。
  你说的/0的问题,我当然明白,你还是要我定义静态数组?
  那如果是17字节的静态数组,而实际长度是4,假设是ABCD,那么发过去的
就是ABCD#0#0#0#0。。。。了,而不是ABCD#0,
  数据包绝对绝对绝对不是定长的,字符串型都以#0作为分隔符,然后下一字节就是下一个字段
  用流发,呵呵,我现在就是这样的,不过我想知道能不能直接就用结构发出去。。。
 
ABCD#0#0#0...=ABCD#0
他们应该是相等的
 
to 李崇文:
  对于独立的一个字符串,OF COURSE,他们是相等的
  但是对于一串数据:
  System_id:pchar; //max:16
Password:pchar; //max:9
System_type:pchar; //max:13
  ABC#0#0A#0:这表示分别是ABC,空串,A
  那么:如果用静态数组ABC#0#0#0#0#0.....#0#0#0#0....A#0#0
  你认为该如何取值?
  这还是全部是字符串在一起的情况,如果几个字符串字段之间还夹着BYTE型字段,
它的值也为0。。。。你认为。。。。?
 
我给你做了个测试,发现没问题
type
TTest = packed record
i: Integer;
p: PChar;
end;
procedure SendBuf;
var
t: TTest;
s: string;
begin
t.i := 10;
s := 'My Test String';
GetMem(t.p,Length(s)+1);
StrPCopy(t.p,s);
ClientSocket.Socket.SendBuf(t,SizeOf(TTest));
FreeMem(t.p);
end;

procedure ServerSocketClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
t: TTest;
begin
Socket.ReceiveBuf(t,SizeOf(TTest));
ShowMessage(t.p);
end;
 
to 李崇文:
首先:
  ClientSocket.Socket.SendBuf(t,SizeOf(TTest));
  你能把PCHAR的内容发出去???SIZEOF(TTEST)似乎不足以放下所有内容吧。。。
  而且发出去的是T。P的地址。。
然后不管如何试一下:
  收到的数据根本根本根本就不对。。
 
我测试过,毫无问题
 
to 李崇文:
showmessage(inttostr(sizeof(ttest)));
 结果是8呀,你能把所有内容发出去,那真是没天理。。。
 你找个SNIFFER之类的东西,看一下你发出去的数据到底是什么。。。
 反正我这里不管用你说的方法,自己收,还是用其他东西看,都是错误数据
 
--〉SizeOf(TTest)似乎不足以放下所有内容吧。。。
内容存放在t.p中, 跟SizeOf(TTest)没什么关系,发送的时候只是吧对应结构的
变量指针发送过去,对方接收到就能取出内容,因此SendBuf函数中的Count参数
应为TTest所占用字节大小,在上面的例子中t.p实际指向'My Test String'的指针
他只需占用4个字节。
---〉收到的数据根本根本根本就不对。。
你把你的测试代码贴出来看看

 
后退
顶部