![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как по UDP (используя Indy) передать файл поблочно. [D7, WinXP]
freak © (2004-05-08 19:19:00)Привет всем мастерам!
Вопрос такой как по UDP (используя Indy) передать файл поблочно. Вернее проблема в том как его получить.
Не хочу использовать всякие там TMemoryStream или TFileStrem. Что если кому-то взбредет в голову отправить файлик размером этак мегабайт 700, в таком случае оперативке конец. Лучше считывать файл блоками и отправлять их.
Вот здесь листинг клиента и сервера. Отправляем IdUDPClient’ом файлик и на удаленной машине получаем IdUDPServer’ом. Клиент отсылает файл полностью, но сервер принимает его не до конца и не посылает ответ, что файл принят. Где я ошибся не могу понять. Помогите уважаемые мастера разобртся.
Часть кода написана по материалам, опубликованным на этом сайте.
{ЛИСТИНГ КЛИЕНТА (посылаем файл)}
procedure TForm1.Button2Click(Sender: TObject);
var FromF: file;
NumRead: Integer;
Buf: array[1..2048] of Char;
EndPrisnak: String;
Count: Integer;
begin
UDPClient.Port := 3030;
UDPClient.Host := '192.168.0.1';
UDPClient.Active := True;
AssignFile(FromF, Edit1.Text);
Reset(FromF, 1);
{перед отправкой файла, посылаем удаленной машине команду-предупреждение, что сейчас будем пересылать файл. Команда содержит имя и размер файла}
UDPClient.Send('file#'+Edit1.Text+'#'+IntToStr(FileSize(FromF))+'#');
{Ждем секунду, пока удаленная машина переходит в режим приема файла, хотя этого можно и не делать}
Sleep(1000);
{Передаем файл}
while FilePos(FromF) <> FileSize(FromF) do
begin
BlockRead(FromF, Buf, SizeOf(Buf), NumRead);
UDPClient.SendBuffer(Buf, SizeOf(Buf));
Label1.Caption := 'Отправленно ' + IntToStr(FilePos(FromF)) + ' из ' + IntToStr(FileSize(FromF));
ProgressBar1.Position := FilePos(FromF) * 100 div FileSize(FromF);
end;
{После передачи, ждем определенный промежуток времени, пока удаленная машина скажет нам, что прием файла закончен. Время ожидания задается в свойстве IdUDPClient.ReciveTimeout. Если мы не получим ответ “end”, то считаем, что файл не принят}
UDPClient.ReceiveBuffer(EndPrisnak, SizeOf(EndPrisnak));
if EndPrisnak <> 'end' then
ShowMessage(‘Прием файла на удаленной машине прошел не удачно.’)
else
CloseFile(FromF);
end;
{ЛИСТИНГ СЕРВЕРА (Принимаем файл)}
private
{ Private declarations }
Name: string;
Size: integer;
Receive: boolean;
ToF: file;
NumWritten: Integer;
procedure TForm1.FormCreate(Sender: TObject);
begin
UDPServer.Active:=True;
Receive := false;
end;
procedure TForm1.Writing(AData: TStream; ABinding: TIdSocketHandle);
var s:String;
begin
if FilePos(ToF) < Size then
BlockWrite(ToF, AData, AData.Size, NumWritten);
ProgressBar1.Position := FilePos(ToF)*100 div Size;
Label3.Caption := 'Принято ' + IntToStr(FilePos(ToF)) + ' из ' + IntToStr(Size);
Label4.Caption := 'Размер блока: '+IntToStr(AData.Size);
if FilePos(ToF) = Size then
begin
Receive := false;
CloseFile(ToF);
s := 'end';
ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, s[1], Length(s));
end;
end;
procedure TForm1.UDPServerUDPRead(Sender: TObject; AData: TStream;
ABinding: TIdSocketHandle);
var Rtext: string; // ???????? ?????
DataStringStream: TStringStream;
begin
if Receive then
Writing(AData, ABinding)
else
DataStringStream := TStringStream.Create('');
DataStringStream.CopyFrom(AData, AData.Size);
Rtext := DataStringStream.DataString;
DataStringStream.Free;
if Copy(Rtext, 0, Pos('#', Rtext) -1) = 'file' then
begin
Delete(Rtext, 1, Pos('#', Rtext));
Name := ExtractFileName(Copy(Rtext, 0, Pos('#', Rtext) -1));
Delete(Rtext, 1, Pos('#', Rtext));
Size := StrToInt(Copy(Rtext, 0, Pos('#', Rtext) -1));
Delete(Rtext, 1, Pos('#', Rtext));
Label1.Caption := ‘Размер файла: ‘ + IntToStr(Size) + ' байт';
Label2.Caption := 'Имя файла: ' + Name;
AssignFile(ToF, 'C:\' + Name);
Rewrite(ToF, 1);
Receive := true;
Writing(AData, ABinding);
end;
end;
Anatoly Podgoretsky (2004-05-09 12:22:00) [1]TFileStrem не отличается от нетипизированых файлов, только удобнее.
Реализованый протокол по сути не отличается от TCP только медленее из за задержок ожидание на ответа и вероятно менее надежный.
freak (2004-05-09 01:51:00) [2]UDP - это принципиально важно. Не могу использовать другой протокол. Тем более если использовать TMemoryStream или TFileStrem то передача проходит нормально. Проблеммы возникают правда если передоваемый файл больше размера буфера IdUDPClient/Server. Но как уже говорил всякие Stream'ы мне не подходят.
Rouse_ (2004-05-08 20:09:00) [3]Код не разбирал...
Не желательно передавать данные которые должны быть приняты полностью (в отличие к примеру от звуковых потоков) без искажений при помощи UDP...
Именно для этого есть другие протоколы...