Так как исправить ошибку в Д2010 не удалось, компилил в Д2006, вынесу всё в отдельный модуль .ЕХЕ и посредством командной строки будет передаваться параметр.
"нестабильность" решил при помощи повторного скачивания файла (t1.interval=800)
сервер
Код:
var
MS :TMemoryStream;
...
procedure TForm1.Button1Click(Sender: TObject);
var
Size: integer;
P: ^Byte;
begin
if OpenDialog1.Execute then
begin
MS.Clear;
MS.LoadFromFile(OpenDialog1.FileName);
ServerSocket1.Socket.Connections[0].SendText('file#'+extractfilename(OpenDialog1.FileName)+'#'+IntToStr(MS.Size)+'#');
MS.Position := 0;
P := MS.Memory;
Size := ServerSocket1.Socket.Connections[0].SendBuf(P^, MS.Size);
memo1.Lines.Add('Отправлено '+IntToStr(Size)+' из '+IntToStr(MS.Size)+' байт')
end;
end;
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
CanClose:=false;
MS.Destroy;
ServerSocket1.Active:=false;
CanClose:=true;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
MS := TMemoryStream.Create;
end;
procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
memo1.Lines.Add('Connect: '+Socket.RemoteAddress);
end;
procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
memo1.Lines.Add('Disconnect: '+Socket.RemoteAddress);
end;
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var P: ^Byte; Size: integer; re:string;
begin
re:= Socket.ReceiveText;
if re = '#end#' then memo1.Lines.Add('Клиент принял файл');
if re = '#rep#' then
begin
ServerSocket1.Socket.Connections[0].SendText('file#'+extractfilename(OpenDialog1.FileName)+'#'+IntToStr(MS.Size)+'#');
MS.Position := 0;
P := MS.Memory;
Size := ServerSocket1.Socket.Connections[0].SendBuf(P^, MS.Size);
end;
end;
end.
клиент
Код:
procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
private
Name: string;
Size: integer;
Receive: boolean;
MS: TMemoryStream;
P: ^Byte;
public
..
end;
var
Form1: TForm1;
rep:boolean;
implementation
{$R *.dfm}
procedure TForm1.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
begin
if rep then
begin
rep:=false;
ClientSocket1.Socket.SendText('#rep#');
end;
end;
procedure TForm1.ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
memo1.Lines.Add('Ошибка связи: '+inttostr(ErrorCode));
ErrorCode:=0;
Receive := false;
end;
procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
var
Rtext: string;
L:integer;
begin
if Receive then
begin
if MS.Size < Size then
begin
t1.Enabled:=false;
L:=Socket.ReceiveLength;
Socket.ReceiveBuf(P,L);
MS.WriteBuffer(P,L);
ProgressBar1.Position := MS.Size*100 div Size;
Label1.Caption:='Принято '+IntToStr(MS.Size)+' из '+IntTostr(Size);
t1.Enabled:=true;
end;
if MS.Size = Size then
begin
t1.Enabled:=false;
Receive := false;
MS.Position := 0;
if fileexists(extractfilepath(paramstr(0))+Name) then
deletefile(extractfilepath(paramstr(0))+Name) ;
MS.SaveToFile(extractfilepath(paramstr(0))+Name);
ClientSocket1.Socket.SendText('#end#');
MS.Clear;
memo1.Lines.Add('Файл принят');
end;
end
else
begin
Rtext:=Socket.ReceiveText;
if Copy(Rtext, 0, Pos('#', Rtext) -1) = 'file' then
begin
t1.Enabled:=false;
Delete(Rtext, 1, Pos('#', Rtext)); // Определяем имя файла
Name := Copy(Rtext, 0, Pos('#', Rtext) -1); // Определяем имя файла
Delete(Rtext, 1, Pos('#', Rtext)); // Определяем размер файла
Size := StrToInt(Copy(Rtext, 0, Pos('#', Rtext) -1)); // Определяем размер файла
Delete(Rtext, 1, Pos('#', Rtext)); // Удаляем последний разделитель
Receive := true;
t1.Enabled:=true;
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
rep:=false; // повтор скачивания
MS := TMemoryStream.Create;
ClientSocket1.Open;
Receive := false;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
MS.Destroy;
end;
procedure TForm1.t1Timer(Sender: TObject);
begin
t1.Enabled:=false;
MS.Clear; MS.Position:=0;
Receive := false;
memo1.Lines.Add('Ошибка получения файла, повтор..');
ClientSocket1.Close;
sleep(1000); // время для переподключения
ClientSocket1.Open;
rep:=true;
end;
end.
Стоит заметить: "Недополучение блоков данных" происходит при передаче очень мелких файлов (<100кб), крупные летят без запинки