Z
zhao_haili
Unregistered / Unconfirmed
GUEST, unregistred user!
前阵子用Socket做了一个多线程文件传输的控件,实现同时响应多个用户多个文件的同时下载(一个文件只用一个线程),存在问题描述:
在XP系统之间,以及2K系统向XP系统传输文件时,控件能正常工作;但在XP向2K系统传输文件时就是出现多传的问题(即传一个5000KB的文件,传输结果会是5290KB,两个数据没有直接联系),情况严重的会导致文件不能用。
我的SendBuffer=1024; RecvBuffer=8192;(个人理解Socket的最大缓存为8K)
如果SendBuffer=32; RecvBuffer=8192;传输50M以内的文件没有问题,大点的文件就会出现“多传”。附发送与接收线程代码:
发送线程代码:
procedure SendTHread.Execute;
var
canDo :TFDSet;
TimeDelay :TimeVal;
Len :Integer;
Sock :TSocket;
Addr :TSockAddrin;
Buffer ointer;
Counter :TTimer;
begin
SetFDValue(PSock,canDo);
TimeDelay := GetTimeValue(20,0);
if (select(0, @canDo,nil,nil,@TimeDelay)>0) and (not Terminated) then
begin
Len := sizeOf(Addr);
Sock := accept(PSock,@Addr,@Len);
if Sock<>SOCKET_ERROR then
begin
PFile := TFileStream.Create(PFilename,fmOpenRead or fmShareCompat or fmShareDenyNone);
PFile.Position := 0;
SetDelay(Sock);
SetFDValue(Sock,canDo);
Synchronize(onBegin);
Getmem(Buffer,SendByte);
Counter := TTimer.Create(nil);
Counter.OnTimer := onTime;
try
PTime := Now;
while PFile.Position < PFile.Size do
begin
if (Terminated) or (select(0,nil,@canDo,nil,@TimeDelay)<=0) then
raise Exception.Create('')
else
if FD_ISSET(Sock,canDo) then
begin
Len := PFile.Size-PFile.Position;
if Len > SendByte then
Len := SendByte;
PFile.ReadBuffer(Buffer^,Len);
if send(Sock,Buffer^,Len,0)=-1 then
raise Exception.Create('');
Application.ProcessMessages;
end;
end;
Synchronize(onProgress);
Synchronize(onComplete);
except
Synchronize(onError);
end;
Counter.Free;
Freemem(Buffer);
CloseSocket(Sock);
PFile.Free;
end;
end;
CloseSocket(PSock);
end;
接收线程代码:
procedure RecvTHread.Execute;
var
Len :Integer;
canRead :TFDSet;
Sock :TSocket;
TimeDelay :TimeVal;
Buffer ointer;
Counter :TTimer;
begin
if not Terminated then
begin
Sock := CreateClient(PTaskData^.FileData.FileSendIP, PPort);
if Sock <> SOCKET_ERROR then
begin
PFile := TFilestream.Create(PFilename,fmCreate);
SetDelay(Sock);
SetFDValue(Sock,canRead);
TimeDelay := GetTimeValue(20,0);
Synchronize(onBegin);
Getmem(Buffer,RecvByte);
Counter := TTimer.Create(nil);
Counter.OnTimer := onTime;
try
PTime := Now;
repeat
if (Terminated) or (select(0,@canRead,nil,nil,@TimeDelay)<=0) then
raise Exception.Create('')
else
if FD_ISSET(Sock,canRead) then
begin
ioctlsocket(Sock, FIONREAD, Len);
if Recv(Sock,Buffer^,Len,0)=0 then
raise Exception.Create('');
PFile.WriteBuffer(Buffer^,Len);
Application.ProcessMessages;
end;
until PFile.Size = PTaskData.FileData.FileSize;
Synchronize(onProgress);
Synchronize(onComplete);
except
Synchronize(onError);
end;
Counter.Free;
Freemem(Buffer);
PFile.Free;
CloseSocket(Sock);
end;
end;
end;
请各位大侠进来讨论,谢谢!
在XP系统之间,以及2K系统向XP系统传输文件时,控件能正常工作;但在XP向2K系统传输文件时就是出现多传的问题(即传一个5000KB的文件,传输结果会是5290KB,两个数据没有直接联系),情况严重的会导致文件不能用。
我的SendBuffer=1024; RecvBuffer=8192;(个人理解Socket的最大缓存为8K)
如果SendBuffer=32; RecvBuffer=8192;传输50M以内的文件没有问题,大点的文件就会出现“多传”。附发送与接收线程代码:
发送线程代码:
procedure SendTHread.Execute;
var
canDo :TFDSet;
TimeDelay :TimeVal;
Len :Integer;
Sock :TSocket;
Addr :TSockAddrin;
Buffer ointer;
Counter :TTimer;
begin
SetFDValue(PSock,canDo);
TimeDelay := GetTimeValue(20,0);
if (select(0, @canDo,nil,nil,@TimeDelay)>0) and (not Terminated) then
begin
Len := sizeOf(Addr);
Sock := accept(PSock,@Addr,@Len);
if Sock<>SOCKET_ERROR then
begin
PFile := TFileStream.Create(PFilename,fmOpenRead or fmShareCompat or fmShareDenyNone);
PFile.Position := 0;
SetDelay(Sock);
SetFDValue(Sock,canDo);
Synchronize(onBegin);
Getmem(Buffer,SendByte);
Counter := TTimer.Create(nil);
Counter.OnTimer := onTime;
try
PTime := Now;
while PFile.Position < PFile.Size do
begin
if (Terminated) or (select(0,nil,@canDo,nil,@TimeDelay)<=0) then
raise Exception.Create('')
else
if FD_ISSET(Sock,canDo) then
begin
Len := PFile.Size-PFile.Position;
if Len > SendByte then
Len := SendByte;
PFile.ReadBuffer(Buffer^,Len);
if send(Sock,Buffer^,Len,0)=-1 then
raise Exception.Create('');
Application.ProcessMessages;
end;
end;
Synchronize(onProgress);
Synchronize(onComplete);
except
Synchronize(onError);
end;
Counter.Free;
Freemem(Buffer);
CloseSocket(Sock);
PFile.Free;
end;
end;
CloseSocket(PSock);
end;
接收线程代码:
procedure RecvTHread.Execute;
var
Len :Integer;
canRead :TFDSet;
Sock :TSocket;
TimeDelay :TimeVal;
Buffer ointer;
Counter :TTimer;
begin
if not Terminated then
begin
Sock := CreateClient(PTaskData^.FileData.FileSendIP, PPort);
if Sock <> SOCKET_ERROR then
begin
PFile := TFilestream.Create(PFilename,fmCreate);
SetDelay(Sock);
SetFDValue(Sock,canRead);
TimeDelay := GetTimeValue(20,0);
Synchronize(onBegin);
Getmem(Buffer,RecvByte);
Counter := TTimer.Create(nil);
Counter.OnTimer := onTime;
try
PTime := Now;
repeat
if (Terminated) or (select(0,@canRead,nil,nil,@TimeDelay)<=0) then
raise Exception.Create('')
else
if FD_ISSET(Sock,canRead) then
begin
ioctlsocket(Sock, FIONREAD, Len);
if Recv(Sock,Buffer^,Len,0)=0 then
raise Exception.Create('');
PFile.WriteBuffer(Buffer^,Len);
Application.ProcessMessages;
end;
until PFile.Size = PTaskData.FileData.FileSize;
Synchronize(onProgress);
Synchronize(onComplete);
except
Synchronize(onError);
end;
Counter.Free;
Freemem(Buffer);
PFile.Free;
CloseSocket(Sock);
end;
end;
end;
请各位大侠进来讨论,谢谢!