Форум: "Сети";
Текущий архив: 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.48 MB
Время: 0.006 c