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

Как обычно, работа сервера начинается с инициализации слушающего сокета, выполняющейся при нажатии кнопки Запустить (листинг 2.50).

Листинг 2.50. Инициализация сервера, основанного на сообщениях

procedure TServerForm.BtnStartServerClick(Sender: TObject);

var

 // Адрес, к которому привязывается слушающий сокет

 ServerAddr: TSockAddr;

begin

 // Формируем адрес для привязки.

 FillChar(ServerAddr.sin_zero, SizeOf(ServerAddr.sin_zero), 0);

 ServerAddr.sin_family := AF_INET;

 ServerAddr.sin_addr.S_addr := INADDR_ANY;

 try

  ServerAddr.sin_port := htons(StrToInt(EditPortNumber.Text));

  if ServerAddr.sin_port = 0 then

  begin

   MessageDlg('Номер порта должен находиться в диапазоне 1-65535',

    mtError, [mbOK], 0);

   Exit;

  end;

  // Создание сокета

  FServerSocket := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  if FServerSocket = INVALID_SOCKET then

  begin

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

    GetErrorString, mtError, [mbOK], 0);

   Exit;

  end;

  // Привязка сокета к адресу

  if bind(FServerSocket, ServerAddr, SizeOf(ServerAddr)) = SOCKET_ERROR then

  begin

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

    GetErrorString, mtError, [mbOK], 0);

   closesocket(FServerSocket);

   Exit;

  end;

  // Перевод сокета в режим прослушивания

  if listen(FServerSocket, SOMAXCONN) = SOCKET_ERROR then

  begin

   MessageDlg('Ошибка при переводе сокета в режим прослушивания:'#13#10 +

    GetErrorString, mtError, [mbOK], 0);

   closesocket(FServerSocket);

   Exit;

  end;

  // Связь слушающего сокета с событием FD_ACCEPT

  if WSAAsyncSelect(FServerSocket, Handle,

WM_ACCEPTMESSAGE, FD_ACCEPT) = SOCKET_ERROR then

  begin

   MessageDlg('Ошибка при установке асинхронного режима ' +

    'cлушающего сокета:'#13#10 + GetErrorString, mtError, [mbOK], 0);

   closesocket(FServerSocket);

   Exit;

  end;

  // Перевод элементов управления в состояние "Сервер работает"

  LabelPortNumber.Enabled := False;

  EditPortNumber.Enabled := False;

  BtnStartServer.Enabled := False;

  LabelServerState.Caption := 'Сервер работает';

 except

  on EConvertError do

   // Это исключение может возникнуть только в одном месте -

   // при вызове StrToInt(EditPortNumber.Text)

   MessageDlg('"' + EditPortNumber.Text +

    '" не является целый числом', mtError, [mbOK], 0);

  on ERangeError do

   // Это исключение может возникнуть только в одном месте -

   // при присваивании значения номеру порта

   MessageDlg('Номер порта должен находиться в диапазоне 1-65535',

    mtError, [mbOK], 0);

 end;

end;

Этот код мало чем отличается от того, что мы уже видели (сравните, например, с листингами 2.19 и 2.30). Единственное существенное отличие здесь — вызов функции WSAAsyncSelect после перевода сокета в режим прослушивания. Этот вызов связывает событие FD_ACCEPT с сообщением WM_ACCEPTMESSAGE.

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