Форум: "Сети";
Текущий архив: 2004.07.04;
Скачать: [xml.tar.bz2];
ВнизКак по UDP (используя Indy) передать файл поблочно. Найти похожие ветки
← →
freak (2004-05-08 19:19) [0]Привет всем мастерам!
Вопрос такой как по 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;
← →
Rouse_ © (2004-05-08 20:09) [1]Код не разбирал...
Не желательно передавать данные которые должны быть приняты полностью (в отличие к примеру от звуковых потоков) без искажений при помощи UDP...
Именно для этого есть другие протоколы...
← →
freak (2004-05-09 01:51) [2]UDP - это принципиально важно. Не могу использовать другой протокол. Тем более если использовать TMemoryStream или TFileStrem то передача проходит нормально. Проблеммы возникают правда если передоваемый файл больше размера буфера IdUDPClient/Server. Но как уже говорил всякие Stream"ы мне не подходят.
← →
Anatoly Podgoretsky © (2004-05-09 12:22) [3]TFileStrem не отличается от нетипизированых файлов, только удобнее.
Реализованый протокол по сути не отличается от TCP только медленее из за задержок ожидание на ответа и вероятно менее надежный.
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2004.07.04;
Скачать: [xml.tar.bz2];
Память: 0.46 MB
Время: 0.076 c