Чтение онлайн

на главную - закладки

Жанры

О чём не пишут в книгах по Delphi

Григорьев Антон Борисович

Шрифт:
Листинг 2.49. Пример простого сервера на асинхронных сокетах

unit Unit1;

interface

uses

 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, WinSock;

const

 WM_SOCKETEVENT = WM_USER + 1;

type

 TForm1 = class(TForm)

procedure FormCreate(Sender: TObject);

procedure FormDestroy(Sender: TObjеct);

 private

ServSock: TSocket;

procedure WMSocketEvent(var Msg: TMessage); message WM_SOCKETEVENT;

 end;

var

 Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);

var

 Data: TWSAData;

 Addr: TSockAddr;

begin

 WSAStartup($101, Data);

 //
Обычная последовательность действий по созданию сокета,

 // привязке его к адресу и установлению на прослушивание

 ServSock := socket(AF_INET, SOCK_STREAM, 0);

 Addr.sin_family := AF_INET;

 Addr.sin_addr.S_addr := INADDR_ANY;

 Addr.sin_port := htons(3320);

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

 bind(ServSock, Addr, SizeOf(Addr));

 listen(ServSock, SOMAXCONN);

 // Перевод сокета в асинхронный режим. Кроме события FD_ACCEPT

 // указаны также события FD_READ и FD_CLOSE, которые никогда не

 // возникают на сокете, установленном в режим прослушивания.

 // Это сделано потому, что сокеты, созданные с помощью функции

 // accept, наследуют асинхронный режим, установленный для

 // слушающего сокета. Таким образом, не придется вызывать

 // функцию WSAAsyncSelect для этих сокетов - для них сразу

 // будет назначен обработчик событий FD_READ и FD_CLOSE.

 WSAAsyncSelect(ServSock, Handle, WM_SOCKETEVENT, FD_READ or FD_ACCEPT or FD_CLOSE);

end;

procedure TForm1.FormDestroy(Sender: TObject);

begin

 closesocket(ServSock);

 WSACleanup;

end;

procedure TForm1.WMSocketEvent(var Msg: TMessage);

var

 Sock: TSocket;

 SockError: Integer;

begin

 Sock := TSocket(Msg.WParam);

 SockError := WSAGetSelectError(Msg.lParam);

 if SockError <> 0 then

 begin

//
Здесь должен быть анализ ошибки

closesocket(Sock);

Exit;

 end;

 case WSAGetSelectEvent(Msg.lParam) of

 FD_READ: begin

// Пришел запрос от клиента. Необходимо прочитать данные,

// сформировать ответ и отправить его.

 end;

 FD_АССЕРТ: begin

// Просто вызываем функция accept. Ее результат нигде не

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

// начинает работать в асинхронном режиме, и его дескриптор

// при необходимости будет передан через Msg.wParam при

// возникновение события

accept(Sock, nil, nil);

 end;

 FD_CLOSE:

 begin

// Получив от клиента сигнал завершения, сервер, в принципе,

// может попытаться отправить ему данные. После этого сервер

// также должен закрыть соединение со своей стороны

shutdown(Sock, SD_SEND);

closesocket(Sock);

 end;

 end;

end;

end.

Преимущество такого сервера по сравнению с сервером, основанным на функции

select
, заключается в том, что он не должен постоянно проверять наличие полученных данных — когда данные поступят, он без дополнительных усилий получит уведомление об этом. Кроме того, этот сервер не имеет проблем, связанных с количеством сокетов в множестве типа
TFDSet
. Впрочем, последнее несущественно, т.к. при таком количестве клиентов сервер обычно реализует другие, более производительные способы взаимодействия с клиентами.

2.2.6. Пример сервера, основанного на сообщениях

В этом разделе мы напишем сервер, использующий асинхронные сокеты и их сообщения (пример AsyncSelectServer на компакт-диске). Этот сервер будет во многом похож на сервер на основе неблокирующих сокетов (см. разд. 2.1.16), только он не станет проверять по таймеру наличие данных в буфере и возможность отправки данных, а будет выполнять это тогда, когда поступят соответствующие сообщения.

Такая схема работы требует более осторожного подхода. По сигналу от таймера мы сами проверяем, на каком этапе в данный момент находится обмен данными с клиентом. Если, например, идет этап отправки данных, то проверять входной буфер сокета не нужно, можно оставить это до тех пор, пока не наступит этап чтения данных. При использовании сообщений приходится учитывать, что сообщение о поступлении данных в буфер сокета может прийти в любой момент, в том числе и тогда, когда обмен с клиентом находится на этапе отправки строки. По протоколу сервер не должен читать сообщение в этот момент, необходимо сначала закончить отправку, поэтому приходится данное уведомление игнорировать. Но второго уведомления система не пришлет, соответственно, после окончания отправки данных сервер должен сам вспомнить, что было уведомление, и перейти к операции чтения.

Поделиться:
Популярные книги

Чужое наследие

Кораблев Родион
3. Другая сторона
Фантастика:
боевая фантастика
8.47
рейтинг книги
Чужое наследие

Бальмануг. Студентка

Лашина Полина
2. Мир Десяти
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Бальмануг. Студентка

Авиатор: назад в СССР

Дорин Михаил
1. Авиатор
Фантастика:
попаданцы
альтернативная история
5.25
рейтинг книги
Авиатор: назад в СССР

Генерал-адмирал. Тетралогия

Злотников Роман Валерьевич
Генерал-адмирал
Фантастика:
альтернативная история
8.71
рейтинг книги
Генерал-адмирал. Тетралогия

На границе империй. Том 6

INDIGO
6. Фортуна дама переменчивая
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.31
рейтинг книги
На границе империй. Том 6

Теневой путь. Шаг в тень

Мазуров Дмитрий
1. Теневой путь
Фантастика:
фэнтези
6.71
рейтинг книги
Теневой путь. Шаг в тень

Защитник

Астахов Евгений Евгеньевич
7. Сопряжение
Фантастика:
боевая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Защитник

Кодекс Охотника. Книга XIII

Винокуров Юрий
13. Кодекс Охотника
Фантастика:
боевая фантастика
попаданцы
аниме
7.50
рейтинг книги
Кодекс Охотника. Книга XIII

Его маленькая большая женщина

Резник Юлия
Любовные романы:
современные любовные романы
эро литература
8.78
рейтинг книги
Его маленькая большая женщина

Проклятый Лекарь IV

Скабер Артемий
4. Каратель
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Проклятый Лекарь IV

Жандарм 4

Семин Никита
4. Жандарм
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Жандарм 4

Тринадцатый V

NikL
5. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Тринадцатый V

Кодекс Охотника. Книга IV

Винокуров Юрий
4. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга IV

Энфис 2

Кронос Александр
2. Эрра
Фантастика:
героическая фантастика
рпг
аниме
5.00
рейтинг книги
Энфис 2