高手请帮看一下,用 WinSocket 传输文件时为什么只能接收不完 (50分)

  • 主题发起人 主题发起人 sky2008
  • 开始时间 开始时间
S

sky2008

Unregistered / Unconfirmed
GUEST, unregistred user!
const
PackSize = 200;

接收数据过程
=================================================

procedure TForm1.RecvData( skt: TSocket );
var
getbuf, putbuf, buf: array[ 0..PackSize ] of char;
TempStream: TMemoryStream;
n, t, i: integer;
begin
Log( '开始接收数据...' );
i := 1;
t := 0;
try
TempStream := TMemoryStream.Create;

repeat

n := recv( skt, buf, PackSize, 0 );
TempStream.WriteBuffer( buf, n );
//Memo1.Lines[ Memo1.Lines.Count - 1 ] := '已接收数据... ' + intToStr( i * PackSize );
inc( t, n );
Log( '已接收数据... ' + intToStr( t ) );
inc( i );
Application.ProcessMessages;
Sleep( 100 );
until n = 0;

TempStream.Position := 0;
memo2.Lines.LoadFromStream( TempStream );
finally
TempStream.Free;
Log( '接收完成!' );
end;
end;


发送数据过程
===================================

procedure TForm1.SendData( skt: TSocket );
var
{getbuf, putbuf, } buf: array[ 0..PackSize ] of char;
TempStream: TMemoryStream;
n, t, i: integer;
begin
Log( '开始发送数据...' );
i := 1;
t := 0;
try
TempStream := TMemoryStream.Create;
Memo2.Lines.SaveToStream( TempStream );
TempStream.Position := 0;
repeat

n := TempStream.Read( buf, PackSize );
send( skt, buf, sizeof( buf ), 0 );
//Memo1.Lines[ Memo1.Lines.Count - 1 ] := '已发送数据... ' + intToStr( i * PackSize );
inc( i );

inc( t, n );
Log( '已发送数据... ' + intToStr( t ) );

Application.ProcessMessages;
sleep( 100 );

until n <> PackSize;

finally
TempStream.Free;
Log( '发送完成!' );
end;
end;
 
log日志显示已接收到 n 字节数据

但完成后为什么 memo2 里只有开始一小部分的数据 ,大概是packSize的大小

也就是说只能收到第一次send的数据

为什么会这样呀?
如何解决?
 
Socket传送数据是发送连续的IP包,如果你处理不及时,会导致数据堵塞(也就是到超过Socket的最大缓冲区),建议在Socket的OnRead事件中处理数据,有多少数据流来就处理多少!
 
也可以用握手方式来解决数据堵塞,服务器端每收到一个包,就发送一个接收成功给客户端
,客户端收到接收成功后才发下一个包。
 
谢谢二位

我想问题出在TMemoryStream里
如果在
n := recv( skt, buf, PackSize, 0 );
后马上
Memo2.line.add( buf );
的话就没有上面的问题

怎么回事呀?
 
Memo2.line.add( buf ); 其实起到了延时的作用,你把它改成一个延时也是一样的,但
是否能成功,可能会取决余计算机的性能。快的计算机可能就不能用了。没有通用性。
 
Delphi自己的Socket组件也是收不完整,
最好自己实现协议或者使用阻塞式传输
 
to LiChaoHui,

用winSock如何用阻塞模式?
 
to Bxch_1000,

我已用了延时了呀
sleep( 100);
还是不行
 
不要用sleep,
用循环试试看。不行就调整 DelayTime 的值,直到成功
for I := 0 to DelayTime do Application.ProcessMessages;
不过我还是建议用握手方式。
 
帮同学做一个作业而已
握手方式麻烦了点
我还是直接收到数据后 Memo2.line.add( buf ); 好了

谢谢各位了
 
多人接受答案了。
 
后退
顶部