Цитата:
Сообщение от 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;