Здравствуйте, Аноним, Вы писали:
А>>в случае меньше — накапливаем в буфер, пока не придет как минимум сколько нужно,
А>>как дождались или в случае больше или равно
А>>накладываем на буфер указатель (PPrefxix) структуры, читаем структуру,
А>>продвигаемся по буферу (или откусываем голову)
А>А как в буфер то напкопить?
А>var Buf: Pointer;
А> Prefix: TPrefix;
А> ReceiveLength: Integer;
А>begin
А> ReceiveLength:=0;
А> if Socket.ReceiveLength>=SizeOf(TPrefix)then
А> Socket.ReceiveBuf(Buf^,SizeOf(TPrefix))
А> else
А> begin
А> while ReceiveLength<=SizeOf(Tprefix)do
А> begin
А> Socket.ReceiveBuf(Buf^,Socket.ReceiveLength);
А> ReceiveLength:=+Socket.ReceiveLength;
А> end;
А> end;
А> Prefix:=PTPrefix(Buf)^;
А>Если длать так, то Buf будет перезаписваться и указывать на адрес новой порции данных?
А>Как мне добавитьв буфер?
А>В Prefix записывается то что я отправил, но в конце процедуры ошибка доступа к памяти.
Правильно, Вы ведь буфер не аллоцируете нигде.
Пользуясь для простоты строкой как буфером (не самое плохое решение, между прочим), делаем примерно так:
type
TclAssoc = ... ваша структура или объект, ассоциированный с сокетом
...
sInputBuffer : ansistring;
...
end;
type
PPrefix=^TPrefix;
TPrefix = packed record
CMD : Integer;
Size : Integer; // я правильно понимаю, что это размер хвоста посылки после префикса?
end;
procedure TForm1.ServerClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
SocketData: TclAssoc;
ptrPrefix: PPrefix;
totalPackSize : cardinal;
sReadPart: ansistring;
sClientNo: ansistring;
begin
// получаем ассоциированную с сокетом структуру данных
SocketData := GetSocketDataBySocket(Socket); <= тут я не знаю как у вас связь сделана
// читаем кусок данных
SetLength(sReadPart, Socket.ReceiveLength);
Socket.ReceiveBuf(sReadPart[1], Length(sReadPart));
// добавляем прочитанный кусок к общему буферу
SocketData.sInputBuffer := SocketData.sInputBuffer + sReadPart;
// разбираем принятые пакеты
while (Length(SocketData.sInputBuffer) > 0) do begin
// если данных совсем мало, даже на хидер не хватает, то перестанем
// тут крутиться и пойдем нафик, ждем когда дошлют еще данных
if (Length(SocketData.sInputBuffer) < SizeOf(TPrefix)) then Break;
// заголовок пришел, проверим, весь-ли хвост имеем.
// в принципе, можно обработать и только заголовок, но сейчас для
// простоты будем ждать посылку целиком
ptrPrefix := @SocketData.sInputBuffer[1];
totalPackSize := (SizeOf(TPrefix) + ptrPrefix^.Size);
if (Length(SocketData.sInputBuffer) < totalPackSize) then Break;
// если мы еще здесь, то как минимум одна посылка уже имеется целиком, обработаем
case Prefix.CMD of
{CMD_LOGIN} 0: begin
sClientNo := Copy(SocketData.sInputBuffer, SizeOf(TPrefix) + 1, ptrPrefix^.Size);
ShowMessage(Format('CMD_LOGIN %s %d', [sClientNo, Length(sClientNo)])); // не очень хорошо тут мессаджи показывать...
end;
2: ;
end;
// убрать обработанную посылку из буфера
Delete(SocketData.sInputBuffer, 1, totalPackSize);
// тут возвращаемся к началу цикла - возможно в буфере есть еще посылки
end;
end;