Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Передача файлов через сокеты [D6, WinXP]


delpher_gray ©   (2002-10-16 13:09:00) 

Господа Делферы !
Подскажите почему не работает этот кусок кода, на приём файла:
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" закачка файла останавливалась.... Подскажите как это сделать !
Заранее благодарен Овсянников Сергей.


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

Ну зачем обязательно потоки??? Ведь поток это тоже буфер. 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;

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


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

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


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

delpher-gray !

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


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

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

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


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

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


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

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


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

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


delpher_gray   (2002-10-20 10:16:00) [8]

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


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

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


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

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

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-18 14:51:00) [11]

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


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

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


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

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


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

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


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

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


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

проще реализовать на тех же 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;


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

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


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

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


Наверх

Титульная страница Поиск, карта сайта Написать письмо