C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

стр.: (2) < [1] 2 >
Indy, Пересылка файлов.
Лена
Отправлено: 31.05.2005, 12:12


Не зарегистрирован







Кто знает, приведите пример, как пересылать файламы при сети на основе компонетов Indy с вкладки Builder. Пример пожалуйста. Спасибо.
Gedeon
Отправлено: 31.05.2005, 12:50


Ветеран

Группа: Модератор
Сообщений: 1742



Какой конкретно протокол Вас интересует?
Лена
Отправлено: 31.05.2005, 13:53


Не зарегистрирован







Меня интересует возможность пересылки двоичных файлов в локальной сети при помощи компонентов IdTCPServer1 и IdTCPClient.
Клиентское приложение отправляет файл из OpenDialog, сервер принимает и рассылает другим компьютерам локальной сети. Пока у меня не получается, и в Интернете работающих примеров не нашла.
Заранее спасибо.
Лена
Отправлено: 31.05.2005, 14:20


Не зарегистрирован







Я так предпологаю, что отсылка из клиента будет выглядеть так:
if(OpenDialog1->Execute())
{

IdTCPClient1->Connect();
IdTCPClient1->WriteFile(OpenDialog1->FileName);
IdTCPClient1->Disconnect();
}

А как прием на сервер организовать для дальнейшей пересылки этого файла другим клиентам?
Gedeon
Отправлено: 31.05.2005, 15:21


Ветеран

Группа: Модератор
Сообщений: 1742



Я тут чуть-чуть покопался, вот что получилось, на форме клиент и сервер, айпи 127.0.0.1 порты есс-но одинаковые
CODE

//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
TFileStream *f = new TFileStream("c:\\iexplore.exe",fmOpenRead);
   IdTCPClient1->Connect();
   IdTCPClient1->OpenWriteBuffer();
IdTCPClient1->WriteStream(f,true,true);
IdTCPClient1->CloseWriteBuffer();
delete f;
IdTCPClient1->Disconnect();

}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdTCPServer1Execute(TIdPeerThread *AThread)
{
   TFileStream *f = new TFileStream("c:\\ie.exe",fmOpenWrite);

AThread->Connection->ReadStream(f,-1,true);


delete f;
}
//---------------------------------------------------------------------------

копируетяся ие нормально, только впереди 4 левых символа, я их удалял в фаре, и после этого эксплорер отлично запускался, дальше ковырять нет времени, пытайтесь разобраться сами или кто еще поможет.

З.Ы. Файл должен существовать на сервере, но его ведь не трудно создать, передав перед фалом его название с пом. WriteLn

Отредактировано Gedeon — 31/05/2005, 15:24
Gedeon
Отправлено: 31.05.2005, 15:45


Ветеран

Группа: Модератор
Сообщений: 1742



Я понял что это за 4 байта — это размер потока, передаваемый в инт.
чтоб этого не было поправьте строку передачи
CODE

IdTCPClient1->WriteStream(f,true,false);


Проверил передачу на соседний ящик, работает.

Отредактировано Gedeon — 31/05/2005, 16:00
Лена
Отправлено: 31.05.2005, 16:15


Не зарегистрирован







Огромное Вам спасибо!!!
Лена
Отправлено: 31.05.2005, 16:30


Не зарегистрирован







Скажите, а если я отправляю этот полученный файл с сервера всем клиентам локальной сети то, как правильно написать отправку? Совокупность слушающих сокетов, используемых сервером, содержится в свойстве Bindings имеющего свойство Items — индексированный массив соединений.
Спасибо.
Лена
Отправлено: 31.05.2005, 17:14


Не зарегистрирован







Eще не большой вопрос:


Отправка с именем файла:

if(OpenDialog1->Execute())
{

TFileStream *f = new TFileStream(OpenDialog1->FileName,fmOpenRead);
IdTCPClient1->Connect();

IdTCPClient1->OpenWriteBuffer();
IdTCPClient1->WriteLn(OpenDialog1->FileName);
IdTCPClient1->CloseWriteBuffer();

IdTCPClient1->OpenWriteBuffer();
IdTCPClient1->WriteStream(f,true,false);
IdTCPClient1->CloseWriteBuffer();
delete f;
IdTCPClient1->Disconnect();

}

Прием на сервере:
Для начала получить имя файла и создать его.

AnsiString S = AThread->Connection->ReadLn();
S = S.SubString( S.LastDelimiter( "\\" ) + 1 , S.Length() );
FileCreate("C:\\Dow\\" + S);

Почему то после выполнения этого кода в папке Dow возникает множество мусора ? –(
Guest
Отправлено: 31.05.2005, 17:22


Не зарегистрирован







Мимоходом:
Есть удобная функция ExtractFileName и иже с ней.
Gedeon
Отправлено: 31.05.2005, 19:41


Ветеран

Группа: Модератор
Сообщений: 1742



Вот пример с созданием файла, никакого мусора
CODE

void __fastcall TForm1::Button1Click(TObject *Sender)
{
   if(OpenDialog1->Execute()){
       IdTCPClient1->Connect();
       IdTCPClient1->WriteLn(OpenDialog1->FileName);
       TFileStream *f = new TFileStream(OpenDialog1->FileName,fmOpenRead);
       //IdTCPClient1->Host = "90.0.0.44";

       IdTCPClient1->OpenWriteBuffer();
       IdTCPClient1->WriteStream(f,true,true);
       IdTCPClient1->CloseWriteBuffer();
       delete f;
       IdTCPClient1->Disconnect();
   }

}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdTCPServer1Execute(TIdPeerThread *AThread)
{
   AnsiString C_Path = "C:\\1\\" + ExtractFileName(AThread->Connection->ReadLn());
Label2->Caption = C_Path;

   if(!FileExists(C_Path)){
    FileCreate(C_Path);
   }
   int size;
size = AThread->Connection->ReadInteger();
   Label1->Caption = size;
TFileStream *f = new TFileStream(C_Path,fmOpenWrite);
   AThread->Connection->ReadStream(f,-1,true);
   delete f;

}
//---------------------------------------------------------------------------

так же Вы получаете размер файла, м. использовать для какого-нить прогреса. Если файл существует, он просто переписывается.
Как файл передать от сервера к клиентам в произвольный момент я не могу сообразить, но наверное как-то можно. Я бы просто повесил на каждого клиента по серверу, а на сервер по клиенту само собой порты пар совпадать не должны и потом таким же способом пересылал файлы на клиентов перебирая их айпи, из Bindings, только тогда Вам нужно дисконект с клиента в основном соединении делать только при завершении его работы, а коннект сразу при запуске проги. Ну тут дальше обрабатывайте напильником под свои нужды.
Лена
Отправлено: 01.06.2005, 08:06


Не зарегистрирован







Еще раз большое спасибо за помощь!!!
Лена
Отправлено: 01.06.2005, 15:18


Не зарегистрирован







На строчке TFileStream *f = new TFileStream(C_Path,fmOpenWrite);
возникает исключение, что не может открыть файл C_Path. Проход с точками останова показывает, что в C_Path все нормально записалось, однако на диске папки с этим файлов не появляется, как будто не сработала ф-ция FileCreate.
Gedeon, подскажите, что не так?

Gedeon
Отправлено: 01.06.2005, 16:01


Ветеран

Группа: Модератор
Сообщений: 1742



Дык папка уже должна существовать. Или она есть, а файл не создается?
Лена
Отправлено: 01.06.2005, 16:15


Не зарегистрирован







1. Создаю папку под именем 6 (код ниже)
2. В момент выполнения приложения на строке
TFileStream *f = new TFileStream(C_Path,fmOpenWrite); возникает исключение Cannot Open file... и программа прерывается.
3. Заглядываю в папку, там нужный файл нулевого размера.
Может это связано с флагом fmOpenWrite? Почему же тогда у Вас работает?

void __fastcall TForm1::IdTCPServer1Execute(TIdPeerThread *AThread)
{
AnsiString C_Path = "C:\\6\\" + ExtractFileName(AThread->Connection->ReadLn());

if(!FileExists(C_Path))
{
FileCreate(C_Path);
}
TFileStream *f = new TFileStream(C_Path,fmOpenWrite);
AThread->Connection->ReadStream(f,-1,true);
delete f;


}


Gedeon
Отправлено: 01.06.2005, 17:01


Ветеран

Группа: Модератор
Сообщений: 1742



Поставьте точку останова на эту строку, затем перейдите в фар или че-нить еще и попробуйте открыть файл на редактирование в каком нить редакторе, если откроется закрывайте редактор и продолжайте выполнение программы, если нет надо искать почему, напишите результат этих действий.
** Лена
Отправлено: 01.06.2005, 17:29


Не зарегистрирован







Пробую сохранить текстовый файл txt.
1. Ставлю точку останова. Открываю фар, вижу свой файл в папке. Он нулевого размера, жму на нем Enter сначала появляется Блокнот затем выскакиваю окно Windows “Процесс не может получить доступ к файлу, так этот файл занят другим процессом”. Жму ОК. Получаю чистый лист в Блокноте.
2. Пробую при точке останова сначала открыть Блокнот затем файл открыть командой Open Блокнота, получаю сообщение “Процесс не может получить доступ к файлу, так этот файл занят другим процессом”.
Я правельно поняла Ваши инструкции?

Gedeon
Отправлено: 01.06.2005, 18:02


Ветеран

Группа: Модератор
Сообщений: 1742



Ну тогда что-то с FileCreate не то, или еще что-то держит файл и не дает его открыть, что возвращает FileCreate? Не может ли кто-то еще открывать только созданный файл? Попробуйте поставить Sleep после создания файла, если он только создался не понятно почему к нему нет доступа, если файл с таким именем уже есть, он не создается, может ли он быть кем-то открыт?
Лена
Отправлено: 01.06.2005, 18:19


Мастер участка

Группа: Участник
Сообщений: 501



Sleep не помогло. Сразу по истечении возникает исключение.
Есть ли замена ф-ции FileCreate? Правда по внешнему виду вроде FileCreate работает — создает файл нулевого размера в нужной папке, вот только почему-то не удается в него записать строкой
TFileStream *f = new TFileStream(C_Path,fmOpenWrite);


sad.gif
Лена
Отправлено: 02.06.2005, 08:28


Мастер участка

Группа: Участник
Сообщений: 501



Попробовала создать полностью новый проект. Все равно возникает исключение на строке записи в файл. sad.gif
Лена
Отправлено: 02.06.2005, 08:55


Мастер участка

Группа: Участник
Сообщений: 501



Ниже код который создает в папке файлы нужного размера:

void __fastcall TForm1::IdTCPServer1Execute(TIdPeerThread *AThread)
{
AnsiString C_Path = "C:\\6\\" + ExtractFileName(AThread->Connection->ReadLn());
int hnd;
if(!FileExists(C_Path))
{
hnd=FileCreate(C_Path);
if(hnd==-1)
{
Application->MessageBox(Не удалось создать...",C_Path.c_str(),MB_ICONEXCLAMATION);
return;
}
FileClose(hnd);
}
TFileStream *f = new TFileStream(C_Path,fmOpenWrite);
AThread->Connection->ReadStream(f,-1,true);
delete f;



}

Однако, например, видео файлы после такой пересылки перестают открываться. sad.gif
Gedeon
Отправлено: 02.06.2005, 11:56


Ветеран

Группа: Модератор
Сообщений: 1742



QUOTE (Лена @ 02/06/2005, 08:55)
Однако, например, видео файлы после такой пересылки перестают открываться. sad.gif

Размер оригинала и полученного файла совпадают?
Лена
Отправлено: 02.06.2005, 12:32


Мастер участка

Группа: Участник
Сообщений: 501



Да, размеры совпадают. Однако те видео файлы, которые попали в папку, после пересылки не открываются. Пишет, как обычно бывает про то, что Media Player открыть не может, хотя все оригиналы открываются без проблем.
Это происходит не только с видео. Без проблем открылся файл — pdf, и gif. В файле doc слетела кодировка, файл psd от Фотошопа тоже не открылся, размеры везде совпадают. Может попробовать другую ф-цию записи? У Indy я нашла ф-цию WriteFile, как Вы думаете Gedeon, ее можно использовать или это не то?
Лена
  Отправлено: 02.06.2005, 12:40


Мастер участка

Группа: Участник
Сообщений: 501



Eще нашла какую то ф-цию — WriteBuffer
Gedeon
Отправлено: 02.06.2005, 13:21


Ветеран

Группа: Модератор
Сообщений: 1742



Сравните файлы командой fc в консоли, если разные, то попробуйте другие функции, я не знаю.
Лена
Отправлено: 02.06.2005, 14:32


Мастер участка

Группа: Участник
Сообщений: 501



Ф-ция WriteFile выдает исключение Cannot Open file.
Как правильно сформировать буфер для WriteBuffer и как получить из этого буфера данные в серверном обработчике?
Кто знает вообще, как без проблем и надежно передавать двоичные файлы по локальной сети? У меня не получилось ни через сокеты ни через Indy.
Если кто знает, укажите адрес в Интернете с надежно работающим примером пересылки файлов в локальной сети на С++ Builder 6 please!!!
Gedeon
Отправлено: 03.06.2005, 15:13


Ветеран

Группа: Модератор
Сообщений: 1742



Ну, Лена, не знаю что у Вас не получается, у меня все работает, проверял видео файлы ~40 Мб все показывает (мож у Вас кодеков нет на удаленном компе?), вордовские файлы, все у меня работает!
Прикладываю проект, исходники и ехе, проверяйте.

У меня ВСВ 6 апд 4, инди — 8.

User Attached Image Скачать файл
tcp_transfer.zip


AVC
Отправлено: 03.06.2005, 15:50


Ветеран

Группа: Модератор
Сообщений: 1583



Хотел попробовать и ...
CODE

void __fastcall TForm1::Button1Click(TObject *Sender)
{
   if(OpenDialog1->Execute()){
     IdTCPClient1->Host = "90.0.0.44";
     Label7->Caption = "Подключение ...";

Зачем sad.gif sad.gif sad.gif
У меня под рукой нет ни 6 ни Indi.
Лена
Отправлено: 03.06.2005, 16:37


Мастер участка

Группа: Участник
Сообщений: 501



Спасибо за помощь, но есть несколько вопросов:
1. Проект не компилируется пишет “Unable to open file ‘ODENBAKH.LIB’, соответственно я не могу получить новый exe.
2. Прилагаемые exe не могу использовать т.к. жестко в коде прописано dTCPClient1->Host = "90.0.0.44";
3. Что за компонент IdAntiFreeze?

Сейчас я просто буду копировать Ваш код, в свое приложении и сообщу о результатах.

Builder у меня 6 SP 4, ну а версию Indy я не знаю как посмотреть, она стандартная — после установки ничего не менялось.
Еще раз спасибо за помощь.


Лена
Отправлено: 03.06.2005, 16:46


Мастер участка

Группа: Участник
Сообщений: 501



Из Вашего кода поняла как узнать версию  — у меня 8.0.25
стр.: (2) < [1] 2 >
Вернуться в Вопросы программирования в C++Builder