Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2002.12.16;
Скачать: [xml.tar.bz2];

Вниз

Передача файлов через сокеты   Найти похожие ветки 

 
delpher_gray   (2002-10-16 13:09) [0]

Господа Делферы !
Подскажите почему не работает этот кусок кода, на приём файла:
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;Socket: TCustomWinSocket);
var
l: Integer;
buf: PChar;
receive: boolean;

begin
if Socket.ReceiveText = "begin" then receive := true;
if Socket.ReceiveText = "end" then receive := false;
if receive then
begin
l := Socket.ReceiveLength;
GetMem(buf,l+1);
Socket.ReceiveBuf(buf^,l);
BlockWrite(f,buf^,l);
FreeMem(buf);
end;
end;

Мне нужно сделать так, чтоб при приёме команды "begin" принемался файл, а при приёме команды "end" закачка файла останавливалась.... Подскажите как это сделать !
Заранее благодарен Овсянников Сергей.


 
Song   (2002-10-16 13:23) [1]

Потому что buf у Вас локальная переменная.


 
YouNick   (2002-10-16 13:43) [2]

Не вдаваясь в подробности, могу сказать, что данный способ (использовать команды "begin" и "end") не корректен. Ведь принимаемый файл может содержать последовательность байт "end". Что тогда? ПО вашему, Delpher_Gray, закачка отсановится, а это неправильно. Есть другие способы организации передачи файлов. ;)
Удачи Вам в вашем начинании ;))


 
Sheriff   (2002-10-16 14:20) [3]

проще реализовать на тех же Indy-ях

Client: (отправитель)
...
s:=ExtractFileName(OpenDialog.FileName);
try
IdCln.Connect;
try
IdCln.Writeln(s);
IdCln.Writeln(Form1.IdCln.LocalName);
IdCln.WriteFile(OpenDialog.FileName,true);
finally IdCln.Disconnect; end;
Memo1.Lines.Add("файл "+s+" отправлен.");
except
Memo1.Lines.Add("Ошибка соединения с получателем.");
end;
...

...у меня отправка была в отдельном потоке...

Server: (получатель)

procedure TForm1.IdSrvExecute(AThread: TIdPeerThread);
var fName,rName: String;
fStream: TFileStream;
begin
fName:=AThread.Connection.Readln;
rName:=AThread.Connection.Readln;
fStream:=TFileStream.Create(ExtractFileDir(ParamStr(0))+"\Recieve\"+fName, fmCreate);
while AThread.Connection.Connected do AThread.Connection.ReadStream(fStream,-1,true);
FreeAndNil(fStream);
AThread.Connection.Disconnect;
Memo1.Lines.Add(fName+" доставлен. "+"Прислал: "+rName);
end;



 
delpher_gray   (2002-10-18 12:16) [4]

Господа Делферы !
Ну тогда уж, можете подсказать готовое решение этой задачи ?
Мне нужно сделать так, чтоб при приёме какой нибудь команды для запуска закачка запускалась, а при команде остановки, закачка останавливалась...
Заранее благодарен !


 
F1   (2002-10-18 12:20) [5]

А что, если передавать не begin и end, а begin и размер данных(надеюсь он заранее известен), и качать в соответствии с размером.


 
Polevi   (2002-10-18 12:49) [6]

размера вполне достаточно


 
F1   (2002-10-18 13:53) [7]

Впринципе согласен с Polevi, но с Begin безопаснее, т. к. может случайно "мусор" какой-нибудь прийти, так мы его отбросим, если нет Begin.


 
delpher_gray   (2002-10-18 14:51) [8]

Да, я с Polevi тоже согласен, но как мне это всё осуществить ?
Да так, чтоб это работало ?


 
F1   (2002-10-18 17:02) [9]

Вот пробную прогу написал для передачи буфера любого размера

procedure TForm1.SpeedButton1Click(Sender: TObject);
var
Data:Array[Word] of Byte;
Length,i:Word;
SL:Integer;
p:^word;
begin
//Это можно менять
Length:=60000;
For i:=2 to Length+1 do
Data[i]:=Ord("1");
Length:=Length+2;
Data[0]:=Length div $FF;
Data[1]:=Length mod $FF;
SL:=ClientSocket1.Socket.SendBuf(Data[0], Length);
StatusBar1.Panels.Items[0].Text:="Send "+IntToStr(SL);
end;

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
l:Integer;
i:word;
St:TFileStream;
begin
if Reading then
begin
L:=Socket.ReceiveLength;
//Обрезание лишних данных
if L>RLength-NLength then
L:=RLength-NLength;
L:=Socket.ReceiveBuf(Data[NLength], L);
NLength:=NLength+L;
StatusBar1.Panels.Items[1].Text:="Recv "+IntToStr(NLength)+" из "+IntToStr(RLength);
if nLength>=RLength then
begin
Reading:=False;
St:=TFileStream.Create("C:\Victor\111.txt", fmCreate);
St.WriteBuffer(Data[2], NLength-2);
St.Free;
end;
end else
begin
Reading:=True;
L:=Socket.ReceiveLength;
L:=Socket.ReceiveBuf(Data[0],L);
RLength:=Data[0]*$FF+Data[1];
NLength:=L;
StatusBar1.Panels.Items[1].Text:="Recv "+IntToStr(NLength)+" из "+IntToStr(RLength);
end;
end;

Написано коряво, но работает. Попробуй что-нибудь в таком духе.


 
delpher_gray   (2002-10-19 20:23) [10]

F1 !
Посмотрел я твой пример...
Он работает нормально, но можешь подсказать как послать какой-нибудь файл ?
Подскажи, если есть время ;-)


 
delpher_gray   (2002-10-20 10:16) [11]

У меня к серверу кроме этого файла, будут идти много разных команд (string), например при приёме команды "test", посылается ответ "test". Мне нужно сделать так, чтоб эти команды и файл не путались !


 
Anatoly Podgoretsky   (2002-10-20 10:28) [12]

Тебе надо разработать уникальную последовательность команд, такую последовательность которая не встретится в файле, например
%COMMAND%test%/COMMAND%


 
Polevi   (2002-10-20 13:11) [13]

а еше лучше рзделить командный поток и поток данных


 
Malder   (2002-10-20 15:42) [14]

Anatoly Podgoretsky 20.10.02 10:28), что-то вы не то говорите. В файле может встретиться какая угодно комбирация байтов...


 
Anatoly Podgorestky   (2002-10-20 15:49) [15]

Polevi © (20.10.02 13:11)
Это еще правильнее

Malder © (20.10.02 15:42)
Вот и свести эту последовательность к минимуму, я думаю у него вполне конкретная задача, что бы с многомиллиарднолетними вероятностями бороться. Вероятность можешь сам прочитать.


 
F1   (2002-10-21 11:06) [16]

delpher-gray !

Во-первых файл вполне можно сделать буфером ;)
А если у тебя много разных команд, то ты их все должен как-то различать. Например каждый поток данных снабжать заголовком, в котором есть размер данных и тип запроса(ответа), и обрабатывать все это как нужно.


 
delpher_gray   (2002-10-21 11:19) [17]

Так значит нужно использовать потоки ?
F1 ! Посмотри вопрос "Передача данных через сокеты", там есть код, но в нём небольшая ошибочка...
Подскажи если знаешь :-)


 
F1   (2002-10-21 13:07) [18]

Ну зачем обязательно потоки??? Ведь поток это тоже буфер. Stream.Data-указатель на этот самый буфер. Попробуй сделать что-нибудь типа:

var
Stream:TMemoryStream;
p:Array of Something;
begin
Stream:=TMemoryStream.Create;
Stream.WriteBuf(DataSize,2);
Stream.Write(Data,DataSize);
p:=Stream.Data;
........................................
// а дальше колбасишь, как угодно, можно как я предлогал.
end;

Ну можно конечно пойти и через потоки, выбор за тобой.



Страницы: 1 вся ветка

Форум: "Сети";
Текущий архив: 2002.12.16;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.007 c
3-51600
Ruf
2002-11-27 18:46
2002.12.16
Летит таблица


4-52007
trotski
2002-11-03 02:51
2002.12.16
Нестандартная форма


1-51672
Sergy
2002-12-04 15:47
2002.12.16
Как заставить перерисоваться TTreeview?


14-51905
LEgO-2
2002-11-22 08:44
2002.12.16
программирование за деньги...


14-51925
Anatoly Podgoretsky
2002-11-25 07:56
2002.12.16
Именинники 25 ноября





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский