Для передачи файла от сервера к клиенту использую код представленный здесь. Возникло несколько проблем: 1. После передачи файла появлялась ошибка пока я не убрал строку Code: MS.Free; // Убиваем буфер 2. После передачи я нахожу файл, размер которого соответствует исходному, но совершенно не пригодный для прочтения (т.е. он не определяется как музыка, если это был mp3 или не открывается для просмотра если это был jpg). Как это можно исправить? Если у кого нибудь есть хороший код для передачи файлов через ServerSocket/ClientSocket так же буду очень благодарен.
код не смотрел но если при освобождении кучи ошибка то значит где то раньше кучу повредил отсюда скорее всего и файл не читаемый получается просто я не паскальщик симптомы сишные обычно именно такие она видать при освобождении кучу проверяет и исключение кидает вот и все ищите повреждение кучи чтобы убедится запустите в релизе если все нормально значит отладочный код кучи который следит за ее состоянием вам сообщает что она испорчена
Вот держи Indy Клиент Code: TFileStream * SF = new TFileStream(Form44-> Edit2->Text, Classes::fmCreate);//куда будем сохранять IdTCPClient1->Disconnect(); IdTCPClient1->Connect(); SF->Position=0; IdTCPClient1->IOHandler->WriteLn("I"); IdTCPClient1->IOHandler->WriteLn(Edit1->Text)//Путь к файлу на удаленном компе IdTCPClient1->IOHandler->ReadStream(SF,-1,false); IdTCPClient1->Disconnect(); if(SF) { delete SF; SF = NULL; } Сервер Code: AnsiString S = AContext->Connection->IOHandler->ReadLn(); if(S[1]=='I') //пришел сигнал отправить файл { TFileStream * SF = new TFileStream(AContext->Connection->IOHandler->ReadLn(), Sysutils::fmOpenRead); AContext->Connection->IOHandler->Write(SF,0,true); delete SF; AContext->Connection->Disconnect();//правильнее поставить в __finally } P.S Будут вопросы пиши , если что могу проэкт готовый отрыть делал когда то
Пожалуйста.Делфи к сожалению нету так что токо C++ Builder,смогу дать токо через часика полтора, надо ?
Лови, там уже и скомпилированные и исходники делал когда то для себя ) Еси че спрашивай http://slil.ru/29480148
да, я знал что будет на Indy. просто серверная часть проекта написана на сокетах, хочется что бы все было в одном стиле)
Я наверно не очень правильно сказал , нельзя передавать прямо так , но можно делить по байтам , я читал что лучше передавать по 8192 байт. (вычитал в книжке "NET. Сетевое программирование для профессионалов") В Инди же можно передавать 1 гигабайт прямо так
Ты совершенно не в теме. На сокетах можно то же, что и на инди, и даже больше. Т..к инди - это обертка вокруг сокетов. И меньше слушай ерунды На send тебе возвращается размер переданного. Если он меньше того, что ты хотел отправить - смещаешь буфер и передаешь дальше. И так до 0 разницы между желаемым и действительным или socket_error -а. Правда не многие знают, что send - функция, даже в очень авторитетных кодах часто опускают проверку результата.
А смысл в этом компоненте, когда без него можно быстрее и красивее все реализовать? Плюс будешь знать, что если баги - ты знаешь того парня, на которого ругаться, а не на таинственных разработчиков индейцев
Возникла проблема. При использовании кода из исходников выше, получается странная вещь... в моем проекте почему то данные передаются с пробелом после каждого символа. Поясню. Например при отправке текстового файла с текстом "Hello, world!", у клиента образуется файл содержание которого "H e l l o , " (при чем как только что оказалось это не пробелмы, т.к. выделить текст и скопировать сюда не получилось). Приведу кратко код отправки и приема: === Отправка === Code: procedure TForm1.Button7Click(Sender: TObject); var Size: Integer; // размерчик P: ^Byte; // указатель в память begin Image1.Picture.SaveToFile('captcha.jpg'); MS.LoadFromFile('captcha.jpg'); // Загружаем файл в буфер // Посылаем информацию о файл (команда # название # размер) Server.Socket.Connections[0].SendText('file#' + 't.txt' + '#' + IntToStr(MS.Size) + '#'); MS.Position := 0; // Переводим каретку в начало файла P := MS.Memory; // Загружаем в переменную "P" файл ClientSocket1.Socket.SendBuf(P^, MS.Size); // Посылаем файл end; === Прием === Code: procedure TForm1.Writing(Text: string); begin if MS2.Size < fSize then // Если принято байт меньше размера файла, то... MS2.Write(Text[1], Length(Text)); // Записываем в буфер ProgressBar1.Position := MS2.Size * 100 div fSize; // Выводим прогресс закачки файла if MS2.Size = fSize then // Если файл принят, то... begin Receive := false; // Переводим клиента в нормальный режим MS2.Position := 0; // Переводим каретку в начало буфера if not(DirectoryExists(ExtractFilePath(ParamStr(0)) + '\' + 'Хранилище Файлов')) then CreateDir(ExtractFilePath(ParamStr(0)) + '\' + 'Хранилище Файлов'); MS2.SaveToFile(ExtractFilePath(ParamStr(0)) + '\' + 'Хранилище Файлов\' + fName); // Сохраняем файл Form1.Client.Socket.SendText('/dend'); // ServerSocket1.Socket.Connections[0].SendText('/dend'); // Посылаем команду "/dend", то есть файл принят // mmoMsg.Lines.Add('[Client]::Принят файл ' + fName); //Запишем в сообщения то что мы приняли файл end; end; procedure TForm1.ClientRead(Sender: TObject; Socket: TCustomWinSocket); var sMessage: string; begin sMessage := Socket.ReceiveText; if Receive then // Если клиент в режиме приёма файла, то... Writing(sMessage) // Записываем данные в буфер else // Если клиент не в режиме приёма файла, то... begin // начинается блок команд if Copy(sMessage, 0, Pos('#', sMessage) - 1) = 'file' then // Если это файл, то... begin MS2 := TMemoryStream.Create; // Создаём буфер для файла Delete(sMessage, 1, Pos('#', sMessage)); // Определяем имя файла fName := Copy(sMessage, 0, Pos('#', sMessage) - 1); // Определяем имя файла Delete(sMessage, 1, Pos('#', sMessage)); // Определяем размер файла fSize := StrToInt(Copy(sMessage, 0, Pos('#', sMessage) - 1)); // Определяем размер файла Delete(sMessage, 1, Pos('#', sMessage)); // Удаляем последний разделитель Receive := true; // Переводим сервер в режим приёма файла Memo1.Lines.Add('[Client]::Пришел файл ' + fName); // запишем в сообщения о том что нам послали файл Memo1.Lines.Add('[Client]::Размер Файла ' + IntToStr(fSize)); // запишем размер файла Writing(sMessage); // Записываем данные в буфер end else Memo1.Lines.Add('[Client]:' + sMessage); // нам пришло текстовое сообщение,так заишем же его end; end; Что здесь можно подправить, дабы исправить эту ошибку?
Еще одна странная вещь... EXE файлы идущие в пример предоставленном Artist прекрасно работали, но после того как я не внося ни каких изменений откомпилировал сервер (принимающую файл сторону) в Delphi 2010 то файлы стали передаваться так же не верно. Вместо "Hello, world!", у клиента образуется файл содержание которого "H e l l o , ". В чем здесь дело?... мне кажется это как то связано с Code: MS2.Write(Text[1], Length(Text)); // Записываем в буфер