Читаем О чём не пишут в книгах по Delphi полностью

 if Connection = nil then

 begin

  AddMessageToLog(

   'Внутренняя ошибка сервера — не найдено соединение для сокета');

  Exit;

 end;

 // Проверяем, были ли ошибки при взаимодействии

 if Msg.SockError <> 0 then

 begin

  AddMessageToLog('Ошибка при взаимодействии с клиентом ' +

   Connection.ClientAddr + ': ' + GetErrorString(Msg.SockError));

  RemoveConnection;

  Exit;

 end;

 // Анализируем, какое событие произошло

 case Msg.SockEvent of

 FD_READ: begin

  // Проверяем, на каком этапе находится взаимодействие с клиентом.

  if Connection.Phase = tpReceiveLength then

  begin

   // Этап получения от клиента длины строки. При выполнении этого

   // этапа сервер получает от клиента длину строки и размещает ее

   // в поле Connection.MsgSize. Здесь приходится учитывать, что

   // теоретически даже такая маленькая (4 байта) посылка может

   // быть разбита на несколько пакетов, поэтому за один раз этот

   // этап не будет завершен, и второй раз его придется

   // продолжать, загружая оставшиеся байты. Connection.Offset -

   // количество уже прочитанных на данном этапе байтов -

   // одновременно является смещением, начиная с которого

   // заполняется буфер.

   Res := recv(Connection.ClientSocket,

    (PChar((PConnection.MsgSize + Connection.Offset)^, Connection.BytesLeft, 0);

   if Res > 0 then

   begin

    // Если Res > 0, это означает, что получено Res байтов.

    // Соответственно, увеличиваем на Res количество прочитанных

    // на данном этапе байтов и на такую же величину уменьшаем

    // количество оставшихся.

    Inc(Connection.Offset, Res);

    Dec(Connection.BytesLeft, Res);

    // Если количество оставшихся байтов равно нулю, нужно

    // переходить к следующему этапу.

    if Connection.BytesLeft = 0 then

    begin

     // Проверяем корректность принятой длины строки

     if Connection.MsgSize <= 0 then

     begin

      AddMessageToLog('Неверная длина строки, от клиента ' +

       Connection.ClientAddr + ': ' + IntToStr(Connection.MsgSize));

      RemoveConnection;

      Exit;

     end;

     // Следующий этап - это чтение самой строки

     Connection.Phase := tpReceiveString;

     // Пока на этом этапе не прочитано ни одного байта

     Connection.Offset := 0;

     // Осталось прочитать Connection.MsgSize байтов

     Connection.BytesLeft := Connection.MsgSize;

     // Сразу выделяем память под строку

     SetLength(Connection.Msg, Connection.MsgSize);

    end;

   end

   elsе if Res = 0 then

   begin

    AddMessageToLog('Клиент ' + Connection.ClientAddr +

     ' закрыл соединение');

    RemoveConnection;

    Exit;

   end

   else

    // Ошибку WSAEWOULDBLOCK игнорируем, т.к. она говорит

    // только о том, что входной буфер сокета пуст, но в целом

    // все в порядке - такое вполне возможно при ложных

    // срабатываниях сообщения

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже