Показать сообщение отдельно
Старый 29.02.2012, 15:17   #155
Пользователь
 
Регистрация: 17.12.2010
Сообщений: 37
Сказал Спасибо: 13
Имеет 1 спасибку в 1 сообщении
glukmaker пока неопределено
По умолчанию

Цитата:
Сообщение от Aries Посмотреть сообщение
И да, сразу совет. Не считывайте все данные из сокета, как те только туда пришли, т.к. может быть ситуация, что пришла только часть пакета.
Правда гуру почему-то советуют все же считывать все данные с сокета в буфер и уже в буфере разбирать их по пакетам...

Вот, когда-то интересовался подобным вопросом.
http://delphimaster.ru/cgi-bin/forum...1319485327&n=4

пришлось вместо первоначального варианта:
Код:
type TPacket: packed record
 case boolean of
 true: (buf: array[0..8191] of byte;);
 false: (len:word;
         typepack:byte;);
 end;

var
 Packet:TPacket;

...
begin
 while true do
   begin
     if recv(FSocket,Packet,2,MSG_PEEK)<2 then Exit;
     if recv(FSocket,Packet,Packet.len,MSG_PEEK)<packet.len then Exit;
     recv(FSocket,Packet,Packet.len,0);
     Obrabotka(Packet); // функция обработки пакета
   end;
end;
переписать приблизительно так (ну это мой вариант на тот момент, сейчас он уже еще доработан, но исходники не при мне):

Код:
...
private
   FBuffer: packed array[0..8191] of byte;
   FStartBuffer:integer;
   FEndBuffer:integer;
...

procedure TMyClass.ReceivePackets;
var
 s:Integer;
begin
 s:=recv(FSocket,FBuffer[FEndBuffer],length(FBuffer)-FEndBuffer,0);

// тут нужно обработать возможные ошибки.

 inc(FEndBuffer,s);
 while true do
   begin
     if FEndBuffer-FStartBuffer<2 then Break;
     move(FBuffer[FStartBuffer],Fpacket,2);
     if FPacket.len>sizeof(FPacket) then
       begin
         // Тут нужно закрыть сокет, и сгенерировать исключение
         // так как прием таких пакетов не планируется
         Exit;
       end;
     if FEndBuffer-FStartBuffer<Fpacket.len then Break;
     move(FBuffer[FStartBuffer],FPacket,Fpacket.len);
     inc(FstartBuffer,Fpacket.len);  // увеличиваем значение стартовой позиции буфера на величину забранных данных
     if FGame then ProcessingGame else ProcessingAuth;  // обработка выделенного пакета
    end;

  // Оптимизация буфера (чтобы обойтись без постоянных сдвигов буфера
  // сдвигать будем только при крайней необходимости)

  // Если буфер пустой, устанавливаем позиции начала и конца на 0
  if FStartBuffer>=FEndBuffer then
  begin
    FStartBuffer:=0;
    FEndBuffer:=0;
  end;
  // Оцениваем длину свободного хвоста буфера, если он менее 2 кб, то сдвигаем данные к началу буфера
  if length(FBuffer)-FEndBuffer<2048 then
  begin
    move(FBuffer[FStartBuffer],FBuffer[0], FEndBuffer-FStartBuffer);
    FEndBuffer:=FEndBuffer-FStartBuffer;
    FStartBuffer:=0;
  end;
end;

Последний раз редактировалось glukmaker, 29.02.2012 в 15:24.
glukmaker вне форума   Ответить с цитированием