急问:idtcpserver怎么接收不同类型的record?

cjf1009 2005-02-03 09:12:46
公共单元里定义不同的record类型,客户端发给服务器端。服务器端的接收代码该如何写?即如何区分发过来的是什么类型的record?

如果在接收线程里写
AThread.Connection.ReadBuffer (CommBlock, SizeOf (CommBlock));

CommBlock是自定义的record,代码在这里是“等停”的,别的类型怎么接收?

demo看过了,不得要领。
...全文
395 32 打赏 收藏 转发到动态 举报
写回复
用AI写文章
32 条回复
切换为时间正序
请发表友善的回复…
发表回复
cjf1009 2005-02-17
  • 打赏
  • 举报
回复
谢谢哈欠老兄的指点。
还想问,你的这个方法和我写的这个有什么区别?

客户端发数据包前先发字符串:
idtcpclient.writeln('login'+'$#$@#');
idtcpclient.writebuffer(loginrec,sizeof(loginrec));

服务器端接收:
command := idtcpserver.readln('$#$@#',5);
if command='login' then
接收loginrec
if command='send' then
接收sendrec
cjf1009 2005-02-05
  • 打赏
  • 举报
回复
哈欠兄,请明示啊

你说的总是有些深,置我于“半蒙半懂”之间,用之不得,弃之不舍。
我做“研究”的功夫实在有限,你的回帖我看了好多遍,可还是不得要领,只好找了这么个别人很少用的办法,却也将信将疑。

还请老兄指点啊
halfdream 2005-02-05
  • 打赏
  • 举报
回复
呵。。写出具体代码往往让你陷入细节,好吧。。

idtcpclient.writebuffer('logn',4);//两方约定这个标志4字节。。这个标志要定长,整个包结构可以变长
idtcpclient.writebuffer(loginrec,sizeof(loginrec));

服务器端接收:
var
command:String;

setlength(command,4);
idtcpserver.readbuffer(pchar(command)^,4);//先读出头标志,
if command='logn' then
接收loginrec//每个标志对应RECORD,这时候应该是知道RECORD长度了。
if command='send' then
接收sendrec


----------------------------------------
当使用AThread.Connection.CurrentReadBuffer时。。

比如对方SEND一块数据过来,也许你要一或两次读CurrentReadBuffer才能读出,因为TCP是数据流服务,无论分多少次读出来的数据,它们都是可靠的数据,你那样处理实际上是强制假设数据要一次
读出,是假设SOCKET提供了同步服务。。。。小部分本来正常的数据,会被处理成错误的。

我看过很多正式使用SOCKET SDK或者TSERVERSOCKET接收数据的代码,都是在假定数据块是一块就读出,有一些是编写者没有这方面意识,另一些编写者则是责任心问题了。


cjf1009 2005-02-04
  • 打赏
  • 举报
回复
helodd 2005-02-04
  • 打赏
  • 举报
回复
var
aa:client_report;
begin

aa.command:='aaaaaa';
aa.msgid:='bbbbbb';
aa.stat:='aaaaa';
idtcpserver.sendbuff('192.167.0.3',12345,aa,sizeof(aa));
end;


在概是这样

对方接收时用

readbuff
halfdream 2005-02-04
  • 打赏
  • 举报
回复
1,这同INDY版本有关.
2,这种用法明显不可靠.

halfdream 2005-02-04
  • 打赏
  • 举报
回复
呵呵..千挑万拣,舍本逐末.....
cjf1009 2005-02-04
  • 打赏
  • 举报
回复
我是想客户端用writebuffer发送,发送的是字符串。如
type
client_report=packed record
command: array [0..1] of char;
msgid: array [0..15] of char;
stat: array [0..6] of char;
end;
cjf1009 2005-02-04
  • 打赏
  • 举报
回复
终于找到了答案:
str := AThread.Connection.CurrentReadBuffer;

这样就可以全部接收了。只是不知道有没有什么缺点没有,为什么没看见有人这么用?
halfdream 2005-02-03
  • 打赏
  • 举报
回复
使用同步字符,或者使用自定义数据包头标志,这都是实现收发同步的手段..
为了让代码更清晰,不主张两种东西混用..

比如HTTP协议是使用回车换行符作同步符发送HTTP头信息,MSN MESSENGER的消息也是类似方法.
RPC协议,DELPHI的TSOCKETCONNECTION使用的协议是使用的数据包方式实现同步.

包头标志一个字节或者四个字节都是比较方便的..因为刚好是一个字符或者一个整型数的长度,
如果用字符串,使用定长字符串.




halfdream 2005-02-03
  • 打赏
  • 举报
回复
command := idtcpserver.readln('',5);

你这个东西用错了。。。。
可以这样用:
用法1:
command := idtcpserver.readln(#13#10,5000);//同步符为 回车换行,超时时间5秒。
这时需要发送方发送的块数据内容不含#13#10符,尾上附加#13#10。


用法2:
command := idtcpserver.readln('!@#$!!#!!#',1000);//同步符为 '!@#$!!#!!#',超时时间5秒。
这种情况,发送端可以这样写:...
var
s:string;

s:='cjf1009到些一游';
idtcpclient.writebuffer(pchar(s)^,length(s));
idtcpclient.writebuffer('!@#$!!#!!#',10);

或者
s:='cjf1009到些一游';
s:=s+'!@#$!!#!!#';
idtcpclient.writebuffer(pchar(s)^,length(s));




cjf1009 2005-02-03
  • 打赏
  • 举报
回复
即:
如何“取數據時, 先取到一個 buffer 或 stream 中, 檢查標志位, 再強制轉成對應的 record 類型”
cjf1009 2005-02-03
  • 打赏
  • 举报
回复
aiirii(ari-爱的眼睛) 老大说的和我看的一个socketserver的例子很像:
var
str : string;
deliver:client_deliver;// 自定义record
report:client_report;// 自定义record
begin
str:=socket.ReceiveText;
IF STR[1]+STR[2]='01' THEN
begin
CopyMemory(@deliver,pchar(str),sizeof(client_deliver));
……
IF STR[1]+STR[2]='02' THEN
begin
CopyMemory(@report,pchar(str),sizeof(client_report));
……
end;

不知在indy的这个控件里如何实现?
aiirii 2005-02-03
  • 打赏
  • 举报
回复
以前做過一個類似的, 我統一在 record 的前兩位, 保留成標志位, 取數據時, 先取到一個 buffer 或 stream 中, 檢查標志位, 再強制轉成對應的 record 類型
huang1023 2005-02-03
  • 打赏
  • 举报
回复
发送和接收的代码完全同indy的那个例子一样,用的是writebuffer,readbuffer,因为我们已把commblock的大小已固定的了,也就是sizeof(CommBlock)是不变的,问题就是封装和解析的Commblock里的数据了,Head标志消息的类型,Size标志Data里有效的数据的大小,当然,我确保data里有效数据的长度是因为我传送的commblock装的是文件流字节块(除了用于握手交流外),
huang1023 2005-02-03
  • 打赏
  • 举报
回复
本人最近也在处理这个问题,对delphi不熟悉,麻烦死了.我想处理的是网络传送文件,定义的record如下:
type CommBlock = record
Head: string[20],
Size: int,
Data: array[1...1024] of byte;
end;
我在data里存放的可是字符串或者是文件流的一段字节块。比如,当文件传送开始时,client向serve发送head的值为QUERY的record,这时data里存放的是一个格式化的字符串,如FromUser$FileName$FileSize。之后当双方传送文件后,data存放的就是文件流字节段的字节块的。我不清楚怎样把字符串和文件流的字节段写到data字节数据中,又怎样读取。刚发了一个帖子,还没人回答
getit911 2005-02-03
  • 打赏
  • 举报
回复
在相应的命令消息中执行就可以区分数据了
IdTCPServerchDateCommand(ASender: TIdCommand);
begin
ASender.Thread.Connection.ReadBuffer (CommBlock, SizeOf (CommBlock));
end;
getit911 2005-02-03
  • 打赏
  • 举报
回复
indy的Demo中有个BasicClientServer->basic command handler server来演示根据命令来处理数据的例子
cjf1009 2005-02-03
  • 打赏
  • 举报
回复
huang1023(啊邦) :
能不能写个小小的例子或几句代码来说明你的观点?
cjf1009 2005-02-03
  • 打赏
  • 举报
回复
(哈欠) 大哥,还是有点不明白那我这个CommBlock要怎么设计?
我现在这样做:
客户端发数据包前先发字符串:
idtcpclient.writeln('login');
idtcpclient.writebuffer(loginrec,sizeof(loginrec));

服务器端接收:
command := idtcpserver.readln('',5);
if command='login' then
接收loginrec
if command='send' then
接收sendrec

不知道这样做行不行,有什么缺点
加载更多回复(12)

1,593

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 网络通信/分布式开发
社区管理员
  • 网络通信/分布式开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧