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

Подключение клиента к серверу выполняется точно так же, как в листинге 2.16, за исключением того, что после выполнения функции connect сокет переводится в асинхронный режим, и его события FD_READ и FD_CLOSE связываются с сообщением WM_SOCKETMESSAGE. Обработчик этого сообщения приведен в листинге 2.66.

Листинг 2.66. Получение данных клиентом

procedure TESClientForm.WMSocketMessage(var Msg: TWMSocketMessage);

const

 // Размер буфера для получения данных

 RecvBufSize = 4096;

var

 // Буфер для получения данных

 RecvBuf: array[0..RecvBufSize - 1] of Byte;

 RecvRes: Integer;

 P: Integer;

begin

 // Защита от "тупой" ошибки

 if Msg.Socket <> FSocket then

 begin

  MessageDlg('Внутренняя ошибка программы — неверный сокет',

   mtError, [mbOK], 0);

  Exit;

 end;

 if Msg.SockError <> 0 then

 begin

  MessageDlg('Ошибка при взаимодействии с сервером'#13#10 +

   GetErrorString(Msg.SockError), mtError, [mbOK], 0);

  OnDisconnect;

  Exit;

 end;

 case Msg.SockEvent of

 FD_READ:

 // Получено сообщение от сервера

 begin

  // Читаем столько, сколько можем

  RecvRes := recv(FSocket, RecvBuf, RecvBufSize, 0);

  if RecvRes > 0 then

  begin

   // Увеличиваем строку на размер прочитанных данных

   P := Length(FRecvStr);

   SetLength(FRecvStr, P + RecvRes);

   // Копируем в строку полученные данные

   Move(RecvBuf, FRecvStr[Р + 1], RecvRes);

   // В строке может оказаться несколько строк от сервера,

   // причем последняя может прийти не целиком.

   // Ищем в строке символы #0, которые, согласно протоколу,

   // являются разделителями строк.

   P := Pos(#0, FRecvStr));

   while P > 0 do

   begin

    AddMessageToRecvMemo('Сообщение от сервера: ' +

     Copy(FRecvStr, 1, P - 1));

    // Удаляем из строкового буфера выведенную строку

    Delete(FRecvStr, 1, P);

    P := Pos(#0, FRecvStr);

   end;

  end

  else if RecvRes = 0 then

  begin

   MessageDlg('Сервер закрыл соединение'#13#10 +

    GetErrorString, mtError, [mbOK], 0);

   OnDisconnect;

  end

  else

  begin

   if WSAGetLastError <> WSAEWOULDBLOCK then

   begin

    MessageDlg('Ошибка при получении данных от клиента'#13#10 +

     GetErrorString, mtError, [mbOK], 0);

    OnDisconnect;

   end;

  end;

 end;

 FD_CLOSE: begin

  MessageDlg('Сервер закрыл соединение', mtError, [mbOK], 0);

  shutdown(FSocket, SD_BOTH);

  OnDisconnect;

 end;

 else begin

  MessageDlg('Внутренняя ошибка программы — неизвестное событие ' +

   IntToStr(Msg.SockEvent), mtError, [mbOK], 0);

  OnDisconnect;

 end;

 end;

end;

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