Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.11.27;
Скачать: CL | DM;

Вниз

Приём команд/файлов   Найти похожие ветки 

 
delpher_gray ©   (2003-09-29 12:27) [0]

Я написал вот такой код:
procedure TMain.ClientSocketRead(Sender: TObject;
Socket: TCustomWinSocket);
label
StreamReceiving,
EndReceiving;
var
Section, CMD: Char; // Section, command
Buf: PChar; // Receive buffer
RLen: integer; // Receive buffer length
Receive: integer; // Size of receive buffer
begin
RLen := Socket.ReceiveLength;
GetMem(Buf, RLen);
Receive := Socket.ReceiveBuf(Buf^, RLen);

if StreamReceive then
begin
if MS.Size < Size then
begin
StreamReceiving:

if Receive > 0 then
MS.Write(Buf^, RLen);

ProgressBar1.Position := MS.Size * 100 div Size;
Label4.Caption := IntToStr(MS.Size);

if MS.Size >= Size then
goto EndReceiving;
end else
begin
EndReceiving:

MS.SetSize(Size);

//LoadFilesList;

StreamReceive := false;
MS.SaveToFile("ms.txt");
MS.Clear;
Size := 0;

ProgressBar1.Position := 0;
end;
end else
begin
if Receive > 0 then
begin
Section := Buf[0];
CMD := Buf[1];

case Section of
"0": // Files operations
case CMD of
"0": // Files list
begin
Size := StrToInt(Copy(Buf, 3, Pos(#13#10, Buf) -3));

Label3.Caption := IntToStr(Size);
StreamReceive := true;
goto StreamReceiving;
end;
end;
end;
end;
end;

FreeMem(Buf);
end;


Это код клиента, клиент принимает команды типа: 001024, где 00 - команда, а всё остальное размер файла...

Пока клиент принимеает только одну команду, но позже сделаю коман намного больше...

Так вот такая проблема: я записываю полученные данные в переменную Buf (PChar), а затем в MemoryStream. Как только скачался весь файл, MemoryStream сохраняется на диске.

В файле получается содержание такого типа:
001024
Код файла


Как мне избавиться от команды ? То есть чтоб в файл записывался только код посылаемого файла ?

И ещё... Подскажите правильно ли я написал программу ? Не нужли что-нибудь в ней срочно менять ?

Заранее благодарен.


 
Digitman ©   (2003-09-29 13:04) [1]

на основании что ты столь верен, что при первом же событии OnRead клиент получит упомянутый префикс "001024" целиком ? А если при первом OnRead придет "0" и лишь при следующем OnRead - все остальное (т.е. "01024") ?

куда пойдет обращение buf[1], если в буфере в этот момент всего 1 байт ?


 
delpher_gray ©   (2003-09-29 15:24) [2]

2Digitman:
Ээээ...
Об этом я не подумал.....
Сделаю !
А ещё есть ошибки ??
И сам вопрос был как вырезать из буфера всё до "#13#10" ?


 
Digitman ©   (2003-09-29 15:47) [3]

а и "вырезать" ничего не надо ... да и зачем вообще <CR><LF> передавать ? измени протокол обмена так, чтобы передающая сторона передавала префикс заранее известного принимающей стороне размера (например, 8 байт : КОП (intrger) + DataSize(Integer))

изначально приним.сторона находится в ожидании приема префикса.
пока она не примет в буфер (за одно или несколько событий OnRead) префикс целиком (т.е. 8 байт), ни о каком последующем приеме файловых данных не может быть и речи

как только префикс принят, идет анализ его КОП (первые 4 байт) и DataSize (следующие 4 байт). Если рез-ты анализа в порядке, приним.сторона переключается в режим ожидания/приема данных, которые опять же за одно или несколько событий OnRead будут каждый раз считываться тобой во врем. буфер и тут же записываться в накопительный поток. Ждать и обрабатывать события в этом режиме следует до тех пор, пока накоп.поток не примет размер, равный ожидаемому (в соответствии с принятым ранее префиксом) размеру DataSize

всех делов)


 
delpher_gray ©   (2003-09-29 15:57) [4]

Ну а если пакеты склеятся ?
Тогда:
001024
Код файла....

Как сделать нормальный приём префикса, я после первого ответа поянл... А вот как отделить префикс от файла ???????


 
Digitman ©   (2003-09-29 16:59) [5]


> Ну а если пакеты склеятся ?


какие еще "пакеты" ?!

ты ждешь 8 байт префикса ? ну и жди их ! ровно 8 байт ! ни больше и не меньше ! зачем считывать в событии OnRead все пришедшее, если тебе требуется всего 8 байт ?

type
TPrefix = packed record
OPCode: Integer;
DataSize: Integer;
end;
PPrefix = ^TPrefix;

var
buf: array[0..4095] of byte;
Prefix: TPrefix;
PrefixOffset : Integer;
DataSize : Integer;
...
режим = прием_префикса;
Offset := 0;
buf := @Prefix;
.....

procedure Объект.OnRead(...);
var
BytesRead: Integer;
begin
if режим = прием_префикса then
begin
BytesRead = Socket.ReceiveBuf(buf[Offset], SizeOf(Prefix) - Offset);
Inc(Offset, BytesRead);
if Offset = SizeOf(Prefix) then
begin
DataSize := PPrefix(@buf)^.DataSize;
режим = прием_данных;
end;
end
else
begin
BytesRead = Socket.ReceiveBuf(buf, Min(DataSize, SizeOf(buf));
запись_BytesRead_байт_из_буфера_в_накопительный_поток;
Dec(DataSize, BytesRead);
if DataSize = 0 then
begin
...
режим := прием_префикса;
Offset := 0;
end;
end;
end;


 
delpher_gray ©   (2003-09-30 15:50) [6]

Млин...
У меня префикс может быть любой длины (до симвова #13#10) !!


 
Digitman ©   (2003-09-30 16:07) [7]

а на кой черт он вообще у тебя текстовый , префикс-то ?

а уж если текстовый, то вместо #13#10 в конце строкового префикса передавай ПЕРЕД ним 4 байта (Integer), значение которых известят принимающую сторону о длине следом передаваемых строковых данных, являющих собой префикс


 
Digitman ©   (2003-09-30 16:11) [8]

можно и 2-мя байтами (Word) обойтись (те же самые #13#10 по размеру получается), если длина стр.данных в префиксе не превышает MAX_WORD


 
delpher_gray ©   (2003-10-01 13:32) [9]

Всё.. Понял...
Всё заработало !
Digitman ! Не мог бы ты объяснить алогоритм работы ??
Я не до конца понимаю (Dec, Min, PPrefix(@buf)^, и т.д....)


 
Digitman ©   (2003-10-01 14:05) [10]


> Dec(DataSize, BytesRead);


вычесть из значения переменной DataSize (хранящей полный размер ожидаемых на этот момент данных) значение переменной BytesRead (куда метод ReceiveBuf только что записал размер очередной принятой "порции" этих ожидаемых данных)


> BytesRead = Socket.ReceiveBuf(buf, Min(DataSize, SizeOf(buf));


попытаться прочитать в буфер Buf порцию ожидаемых данных размера, указанного в DataSize, но не более чем размер буфера (т.е. максим.размер считываемой за один прием порции данных не должен превышать размер буфера, иначе при записи в буфер произойдет выход за границы памяти, отведенные под него)


> DataSize := PPrefix(@buf)^.DataSize;


поскольку буфер представлен в памяти статически и имеет тип array[..] of byte, а содержимое этого буфера в дан.момент есть целиком принятая префиксная структура, то для того чтобы обратиться к полю DataSize этой структуры, мы должны на время представить адрес буфера как указатель на структуру, после чего к полю структуры можно обращаться обычным привычным образом - по имени поля

@buf - компилятор вычисляет адрес буфера

PPrefix(@buf) - "успокаиваем" компилятор, говоря ему , что мы осознанно пытаемся рассматривать в дан.момент адрес буфера как указатель на некую структуру TPrefix

PPrefix(@buf) ^.DataSize - делаем т.н. "разыменование" (в принципе - необязательное в этом контексте, потому что компилятор и без этого поймет, что от него требуется, но зато более наглядное), в рез-те чего получаем значение указателя типа PPrefix ... а указывает он на данные типа TPrefix ... после чего просто обращаемся к полю TPrefix.DataSize по чтению, копируя его содержимое в лок.переменную для дальнейшей работы ... ибо в режиме "прием_данных" новое содержимое буфера затрет старое, хранившее в режиме "прием_префикса" частично или полностью принятый префикс ... кстати не забудь сохранить и поле OPCode для дальн.анализа !



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

Текущий архив: 2003.11.27;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.017 c
1-89975
AndriyS
2003-11-17 15:44
2003.11.27
TWebBrowser


14-90066
ZeroDivide
2003-11-05 16:54
2003.11.27
Ладно, пусть будет с обоснованиеми и без инвенктивной лексики


3-89715
чайник
2003-11-10 09:28
2003.11.27
Ошибка записи данных на сервер


6-90033
inwin
2003-10-01 17:03
2003.11.27
TServerSocket


1-89970
NetKnight
2003-11-17 16:27
2003.11.27
ehLib & ehGrid