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

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.009 c
14-90082
Проходящи_й_
2003-11-05 10:40
2003.11.27
100$ за то, кто узнает sn delphi, версию, систему, sn из exe.


1-89882
Хрюначок
2003-11-15 19:15
2003.11.27
Что делает этот код ??


1-89807
Хрюначок
2003-11-18 17:02
2003.11.27
Архив


3-89775
Reddy
2003-11-07 07:57
2003.11.27
как программно установить курсор на нужный столбец в DBGrid


3-89734
jonni
2003-11-09 04:11
2003.11.27
получить зуначения





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский