使用indytcpserver/indytcpclient在局域网内测试发送4M文件竟然用了20分钟,请看代码(100分)

  • 主题发起人 主题发起人 dfw001
  • 开始时间 开始时间
D

dfw001

Unregistered / Unconfirmed
GUEST, unregistred user!
TCommBlock = record //定义数据传输格式
Command:char; //命令格式,a表示msg是传过来的文件
// b表示msg是传过来的聊天文本
Name:string[10]; //接收人姓名
Msg:array[0..1024] of char; //传送的内容
end;

//分块发送
CommBlock.Command :='a';
CommBlock.Name:='user01';
while 已发送的长度<文件总长度 do
begin
FillChar(CommBlock.Msg ,1025,0);
if 文件总长度-已发送的长度>1025 then
每次发送的长度:=1025
else
每次发送的长度:=文件总长度-已发送的长度;
stream1.Position :=Sendsize;
stream1.Read(CommBlock.msg,每次发送的长度);
//开始传送文件
form1.IdTCPClient1.Socket.Send(CommBlock,sizeof(CommBlock));
inc(已发送的长度,每次发送的长度);
end;
//分块接受
if CommBlock.command='a' then //开始传送文件
begin
i:=sizeof(CommBlock.Msg ); //每次接受的长度
stream1.Write(CommBlock.msg,i);//写文件
i_count:=i_count+i; //累计接受的长度
if i_count>=总长度 then
begin
Freeandnil(Stream1);
Messagebox(handle,'文件发送完毕!','提示息',mb_ok+mb_iconinformation);
end;
end
end;

高手指点一下。如何提高速度! dfw001@tom.com
 
把每次发送的字节数改大。
这个用UDP也可以发的啊。
 
兄弟们帮帮忙啊
 
我没有用过Indy,按说没权力发言。不过我还是想表达我的几点不解:
1.UDP完全可以实现,速度也更快,只是需要改成一问一答式,防止丢包。
2.为什么每次传1025字节?好怪的一个数字。一般每次传送的总长度为2的幂比较好,看你
的结构中Command计4字节;Name计11字节;Msg计1025字节共1040字节,虽然按4字节对
齐,但要是我一定会选择1024字节,也就是Msg长1009字节或者2033字节。
3.接收方如何得到文件长度?当然,有可能是你别的传送过程传的,但既然已经传送了文件
长度,为什么不连Command和Name两个字段随文件长度一次传过去?反正TCP/IP是基于流的。
4.你的传送过程实际上是不停的,这和不分块没什么区别。按我从前不用API时候的经验,
每传送一次加一点延迟效果会更好。我不知道你用的Indy是通过什么机制来驱动,如果通过
事件来驱动则非常简单,直到收到系统的“发送区已空”的通知才发送下一块。
 
奇怪,我就用socket,606k的就一秒多一点。indy是block的。建议用socket!最快!
还有,你的数据分块对于indy是小了点,最好2-4k(对indy)。
 
Indy是基于Block加线程。
很好用
我一点也不觉得慢。
其实根本用不着像作者那样做。
可以先发个命令标志过去,说明接下来的,是聊天文本还是传送文件。

如果传文件,可以先发送文件字节数(用writeinteger),再发送文件名(用
writeln),再发送文件流(用WriteStream)

如果是发送聊天文本的,就用writeln发送。

相应地,接收端,也是根本命令标志,判断聊天文本/传送文件
要一步一步对着干:
writeinteger == readinteger
writeln == readln
writestream == readstream


原理就是这样,不过值得一提的是,如果是小文件(不大于10M)就可以一次性用
writestream发出,如果够大的,就会非常慢,那不是indy的问题,是Delphi的TfileStream
处理问题。建议使用openfile api,然后再用read 分块读入内存,然后再发送,
处理速度将会大大提高。


 
没时间帮你找问题,不过有一个更严重的东东.
不能把TCommBlock = record 当做绶冲区!!!
实在想这样用,就应该是
TCommBlock = Packed Record
否则有可能会有无用字节.

 
怎么又碰到这家伙?到处胡说八道!
在这里使用Record比Packed Record更好,因为系统会为Record分配一个按四字节对齐的结
构。只要收发两端定义一致就毫无问题。反倒是压缩格式读起数据来反而慢。
以后不懂就静悄悄的,别以为自己真的是个专家!

Rocklee认为是文件问题的说法好象也不太对。我用TFileStream扫描过一个100M的文件,用了不到一秒钟。分块读和整块读都试过。应该说TFileStream是可靠的。我建议你测试一下
发送和接收循环的间隔时间比较好,这样很容易找到问题。
 
barton, 呵呵.
看来我还是不要到处乱答,免得被人扁得毫无面子[:D]

 
非常谢谢各位兄弟们的答复
to Rocklee 这样一一对应好象不保险,如果有多人同时聊天,同时发送文件,先发命令,
再发内容我怕缓冲区里的内容次序容易混乱。

to barton 老兄再帮帮我分析原因

此贴我再增加100分,分给上面的兄弟。

 
Indy组件是组塞模式的,是否与这个有关?
把timeout数值改小点?
 
barton
"只要收发两端定义一致就毫无问题"
难道这不是我在提醒的?100m会多出多少个字节?这些字节在cpu中运算快还是在网络中
传输快.
我不答,你也不答,跟在我屁股后面干什么?就因为我指出你老线程中用得不妥的地方?
还有你那两个跟屁X呢?怎么不来?

to dfw001你干嘛不感谢我,我不来的话barton大X又怎么会来?
哈哈,玩笑.别当真.
 
to yanyandt2我试试;
to 参宿四 我把Msg改大试一试。
to real_clq 其实我也不想把TCommBlock = record 当做绶冲区!!!
但为了区分缓冲区里的内容是文本,文件,还是声音,所以我不得不用了一个记录类型,我
也很想只定义Msg:array[0..1024] of char,但没有其他好办法。
兄弟们还有没有其它好办法?
 
其实消息类型你用字符串定义也行吧
command-- name-- text
1个字符 最大20个字符 后面都是内容
然后客户端接收时,处理这样的字符串也很简单。
 
大家看看这个人的嘴脸!还好意思在这混!我是第四个答这个贴的,你把眼睛放亮一点!我
可是没有攻夫和你计较!死瘪三!100m会多出多少字节?倒底是CPU快还是网络传输快?回
去问你老师去!你老师既不教你技术又不教你做人,真是误人子弟!我凭什么跟你讲?

大家不要见怪。大富翁总的来说是个纯净的地方。我也是和大家交流学习,只是容不得个别
人无端破坏气氛。lynn也算是高手一个,我凭什么扁你,只要你不扁我我就高兴得不得了
了。[:D]

dfw001:我也花了些时间好好看你的源码,感觉不出哪儿有问题。我平常遇到这样的问题总
是加入一些计时的代码,然后看看到底是收的问题还是发的问题。有了这个依据,就很快
能够判断出来问题所在了。最简单的处理就是创建一个log文件,记录什么时候开始发送,
什么时候发送完毕;什么时候开始接收,什么时候接收完毕。两个时间表一对照,就能够
判断是哪一边的问题。另外,你不妨在你的记录中加入当前时间这个字段,两边比较更可
靠一些。
 
to 我是指回答字节对齐的问题.
to dfw001一般的做法是将record中的内容写入缓冲区再处理.
速度问题我再看看,现在上班很危险.
 
你不考虑加密、解密,但是要考虑压缩、解压缩啊!
 
//分块接受
if CommBlock.command='a' then //开始传送文件
问题可能在这里,你是不是循环读CommBlock结构,然后找其中的command?
说实话这样做法是比较笨的[别误会,没别的意思].你可以参考smtp,pop3这样
的协议,它们都是先应答,确定对方要接收数据时才发送大块的数据的,而不是每一次都
把这样1k多的东东发过去,然后再做判断.
 
现在把msg加到2048速度快了点。但还要是要10分钟左右。
to barton,我发送,接受都有进度条跟踪显示,感觉发送端和接受端速度一样。
我怀疑是不是我不应该定义record类型.
 
to real_clq 你说的对,每次读取缓冲区中的内容后我再判断command的值然后分别处理
程序的结构是这样的:
form1.IdTCPClient1.ReadBuffer(CommBlock,sizeof(CommBlock));
if CommBlock。command='a' then
//接受文件
else if CommBlock。command='b' then
//显示聊天内容
else if CommBlock。command='c' then
//其他
 
后退
顶部