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

Вниз

Предложите идею, как реализовать....   Найти похожие ветки 

 
Adventure ©   (2003-03-03 11:36) [0]

Ответы от сервера приходят в виде TCP/IP пакетов.
НО! Ответ может придти не в одном пакете, а разбит на несколько.
Причем никогда не известно, какова длина ответа.
Как организовать обработку пакетов?
Пробовал проверять на "незавершенность" данных -> не серьезно.
Сейчас попробую выталкивать пакеты в стек и после сборки всех пакетов в один массив их обрабатывать --> трудоемко.

Может у кого есть идеи или собственные разработки, поделитесь.


 
Digitman ©   (2003-03-03 11:50) [1]

передатчик шлет приемнику dword, содержащий размер следующего следом блока данных

приемник ждет получения dword (организовав буфер размером в sizeof(dword))

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

Исходя из размера реально принятых данных N при каждом чтении в событии OnRead() сч-к декрементируется на N и позиция в буфере инкрементируется также на N. Как только сч-к достигнет нуля, считается, что очер.блок данных принят успешно


 
Adventure ©   (2003-03-03 11:58) [2]


> Digitman © (03.03.03 11:50

Забавное решение.



 
Digitman ©   (2003-03-03 12:06) [3]


> Adventure


и - единственно верное.

ибо - поток есть поток


 
Adventure ©   (2003-03-03 12:26) [4]

Ну я кажется нашел более эллегантное решение. :-)

Спасибо, за помощь.


 
Digitman ©   (2003-03-03 12:29) [5]

Поделись, коль нашел)


 
Adventure ©   (2003-03-03 12:43) [6]

Var Convey: TMemoryStream;

try
FBufferLength:=Socket.ReceiveLength;
Socket.ReceiveBuf(FBuffer,FBufferLength);
if FBuffer[0]=#0 then begin
ParseCommand;
Convey.WriteBuffer(FBuffer,FBufferLength);
end
else begin
Convey.WriteBuffer(FBuffer,FBufferLength);
ParseCommand;
end;

procedure ParseCommand;
begin
Convey.Seek(0,0);
FBufferLength:=Convey.Size;
Convey.ReadBuffer(FBuffer,FBufferLength);
// Обработка
...........................
// Обработка

if {проверка на полноту данных} then Convey.Clear;

end;


 
Digitman ©   (2003-03-03 13:12) [7]

1-е же, что вызывает бооольшие вопросы:

1. Где выделение памяти под FBuffer перед ReceiveBuf() ?
Значение, возвращаемое св-вом ReceiveLength() и должно являться основанием для выделения блока памяти под буфер соотв.размера (не меньшего чем ReceiveLength())

2. На основании чего ты предполагаешь, что после приема какого-то очер.фрагмента потока в какой-то момент времени 0-й байт буфера обязательно будет = #0 ? Чем ты можешь оправдать такое решение (при условии, что твой передатчик непрерывно посылает блоки данных, без ожидания от приемника некоего блока данных, подтверждающего приема и разрешающего посылку след.блока данных) ?
Такой алгоритм теоретически сможет надежно работать лишь при схеме взаимодействия между передатчиком и приемником по принципу "отправка запроса - ожидание ответа - прием ответа", но никак не при работе передатчика в режиме "запрос за запросом, друг за другом непрерывно, прием же ответа - по мере поступления"


 
dimich1978 ©   (2003-03-03 13:33) [8]

Можно делать используя этот юнит
unit LongDataTransfer;

interface
uses ScktComp;
Type TMySProc = procedure(const S:AnsiString) of object;
function SendLongText(Socket:TCustomWinSocket; S:ansiString):boolean;
function ReceiveLongText(Socket:TCustomWinSocket;MySProc:TMySProc;SafeCalledStr :string = ""):boolean;


var
InputBuf : ansiString;
InputDataSize : LongWord;
InputReceivedSize : LongWord;

implementation
function SendLongText(Socket:TCustomWinSocket; S:ansiString):boolean;
Var TextSize:integer;
TSSig : string[4];
begin
Result:=True;
Try
If not Socket.Connected then Exit;
TextSize:=Length(S);
asm
mov EAX,TextSize;
mov dword ptr TSSig[1],EAX;
mov byte ptr TSSig[0],4;

end;
S:=String(TSSig+S);
Socket.SendBuf(Pointer(S)^,Length(S));
except Result:=False;
end;
end;

procedure FlushBuffers;
begin
InputBuf:="";
InputDataSize:=0;
InputReceivedSize:=0;
end;

function ReceiveLongText(Socket:TCustomWinSocket;MySProc:TMySProc;SafeCalledStr :ansistring = ""):boolean;
var
S:ansiString;
RDSize:LongWord;
F:String[4];
begin
Result:=True;
try
If SafeCalledStr="" then begin
RDSize:=Socket.ReceiveLength;
S:=Socket.ReceiveText;
end
else begin

S:=SafeCalledStr;
RDSize:=length(S);
end;
If (Length(InputBuf)<4) and (Length(InputBuf)>0) then begin //?????????????, ? ??? ??????
S:=InputBuf+S; //???? ?????????????? ??? ?????????
FlushBuffers; //????? ??????
end;
If InputBuf="" then
begin //????? ?????? ?????;
F:=Copy(S,0,4);
asm
mov EAX,dword ptr F[1];
mov InputDataSize,EAX;
end;

if InputDataSize=RDSize-4 then begin //???? ???? ? ??????

InputBuf:=Copy(S,5,RDSize-4); //?? ??????, ?? ???????????? ???.
MySProc(InputBuf);
FlushBuffers;
Exit;
end;
if InputDataSize<RDSize-4 then begin //????? ???????.
InputBuf:=Copy(S,5,InputDataSize);
MySProc(InputBuf);
Delete(S,1,InputDataSize+4);
FlushBuffers;
ReceiveLongText(Socket,MySProc,S);
Exit;
end;
if InputDataSize>RDSize-4 then begin //??? ?????? ????????
InputBuf:=Copy(S,5,RDSize-4); //???????? ??????
InputReceivedSize:=RDSize-4;
end;
end
else begin //????? ?????? ?? ????
//InputBuf:=
If RDSize+InputReceivedSize=InputDataSize then
begin //???????? ?????????
InputBuf:=InputBuf+Copy(S,0,RDSize); //???????? ???????
MySProc(InputBuf); //? ??????, ??????
FlushBuffers; // ? ?????? ?????? ???
Exit;
end;
If RDSize+InputReceivedSize<InputDataSize then // ????????
begin //?????????
InputBuf:=InputBuf+Copy(S,0,RDSize); //????????
InputReceivedSize:=InputReceivedSize+RDSize;
Exit;
end;
If RDSize+InputReceivedSize>InputDataSize then //???????? ????????
begin // ?? ? ?????? ???? ??? ?????? - ???????.
InputBuf:=InputBuf+Copy(S,0,InputDataSize-InputReceivedSize);
MySProc(InputBuf);
Delete(S,1,InputDataSize-InputReceivedSize);
FlushBuffers;
ReceiveLongText(Socket,MySProc,S);
end;
end;
except Result:=False;
end;
end;

end.

Пример использования:
.....
Procedure DataProcessing(S:String); //Эта процедура будет обрабатывать
begin //полученные данные, и
ShowMessage(S); //автоматически вызывается каждый
end; //при получении нового блока данных.

//Процедура отправки - по нажатию кнопки отправляем через компонент
//ClientSocket три строки.
procedure TForm1.Button1Click(Sender: TObject);
begin
SendLongText(ClientSocket.Socket,"Первая строчка!");
SendLongText(ClientSocket.Socket,"Вторая строчка!");
SendLongText(ClientSocket.Socket,"Третья строчка! Все три показаны по отдельности!!!");
end;

//Процедура ServerSocket OnClientRead содержит одну строчку
//вызова ReceiveLongText, передавая ей в качесте параметра
//имя вашей процедуры обработки.
procedure TForm1.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
begin
ReceiveLongText(Socket,DataProcessing);
end;



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

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

Наверх




Память: 0.5 MB
Время: 0.011 c
14-77155
Snap
2003-04-06 21:45
2003.04.24
Где можно найти формат файлов патча windows


4-77223
Alpine
2003-02-26 17:03
2003.04.24
Как в всплывающее меню IExplorer - а добавить свою строку ?


14-77116
Pat
2003-04-06 21:39
2003.04.24
Диаметр множества. Объясните что это такое :-))


1-76959
Viktor_bs
2003-04-12 17:26
2003.04.24
Вопрос по написанию компонентов


9-76749
ogo
2002-11-26 11:34
2003.04.24
opengl для delphi