Re[3]: ReceiveBuf Delphi7
От: Аноним  
Дата: 01.06.11 09:51
Оценка: 3 (1)
Здравствуйте, Аноним, Вы писали:


А>>в случае меньше — накапливаем в буфер, пока не придет как минимум сколько нужно,

А>>как дождались или в случае больше или равно
А>>накладываем на буфер указатель (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;
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.