Форум: "Сети";
Текущий архив: 2003.04.24;
Скачать: [xml.tar.bz2];
ВнизПредложите идею, как реализовать.... Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.008 c