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

procedure TServerForm.ProcessConnection(Index: Integer);

var

 // Вспомогательная переменная, чтобы не приводить каждый раз

 // FConnections[Index] к PConnection

 Connection: PConnection;

 // Результат вызова recv и send

 Res: Integer;

 // Вспомогательная процедура, освобождающая ресурсы, связанные

 // с клиентом и удаляющая запись подключения из списка

 procedure RemoveConnection;

 begin

  closesocket(Connection.ClientSocket);

  Dispose(Connection);

  FConnections.Delete(Index);

 end;


begin

 Connection := PConnection(PConnections[Index]);

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

 // Используется оператор if, а не case, потому, что в случае case

 // выполняется только одна альтернатива, а в нашем случае в ходе

 // выполнения этапа он может завершиться, и взаимодействие

 // перейдет к следующему этапу. Использование if позволяет выполнить

 // все три этапа, если это возможно, а не один из них.

 if Connection.Phase = tpReceiveLength then

 begin

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

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

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

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

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

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

  // загружая оставшиеся байты. Connection.Offset — количество

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

  // смещением, начиная с которого заполняется буфер.

  Res := recv(Connection.ClientSocket, (PChar(@Connection.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;

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

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