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

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

Жанры

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

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

Шрифт:

Наш простейший сервер будет использовать только одну нить. Как мы помним, сервер должен вызывать две функции, которые блокируют работу нити: accept и recv. Очевидно, что задействовать их обе сразу в одной нити не получится, именно поэтому наш сервер сможет работать только с одним клиентом одновременно. И чтобы не блокировать пользовательский интерфейс, наш сервер будет консольным приложением. В командной строке ему передается номер порта, к которому привязывается слушающий сокет.

Первое, что должен сделать сервер, — это создать сокет. привязать его к требуемому адресу и перевести в режим прослушивания. Этот код мало чем отличается от приведенного ранее примера создания сокета для UDP (см.

листинг 2.8). Вся разница только в том, что вместо сокета типа
SOCK_DGRAM
создается сокет типа
SOCK_STREAM
, а в конце еще вызывается функция
listen
(листинг 2.14).

Листинг 2.14. Создание сокета в программе SimplestServer

var

 // Порт, который будет "слушать" сервер

 Port: Word;

 // "Слушающей" сокет

 MainSocket: TSocket;

 // Сокет, создающийся для обслуживания клиента

 ClientSocket: TSocket;

 // Адрес "слушающего" сокета

 MainSockAddr: TSockAddr;

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

 ClientSockAddr: TSockAddr;

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

 ClientSockAddrLen: Integer;

 //Без этой переменной не удастся инициализировать библиотеку сокетов

 WSAData: TWSAData;

 StrLen: Integer;

 Str: string;

begin

 try

if ParamCount = 0 then

// Если в командной строке порт не задан, назначаем его

Port := 12345;

else

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

try

Port := StrToInt(ParamStr(1));

if Port = 0 then

raise ESocketException.Create(

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

except

on EConvertError do

raise ESocketException.Create(

'Параметр "' + ParamStr(1) + '" не является целым числом');

on ERangeError do

raise ESocketException.Create(

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

end;

// инициализация библиотеки сокетов

if WSAStartup($101, WSAData) <> 0 then

raise ESocketException.Create(

'Ошибка при инициализации библиотеки WinSock');

// Создание сокета, который затем будет "слушать" порт

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

if MainSocket = INVALID_SOCKET then

raise ESocketException.Create(

'Невозможно
создать слушающий сокет: ' + GetErrorString');

// Формирование адреса для "слушающего" сокета

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

MainSockAddr.sin_family := AF_INET;

// Выбор IP-адреса доверяем системе

MainSockAddr.sin_addr.S_addr := INADDR_ANY;

// Порт назначаем, не забывая перевести его номер в сетевой формат

MainSockAddr.sin_port := htons(Port);

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

if bind(MainSocket, MainSockAddr, SizeOf(MainSockAddr)) = SOCKET_ERROR then

raise ESocketException.Create(

'Невозможно привязать слушающий сокет к адресу: ' +

GetErrorString);

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

if listen(MainSocket, SOMAXCONN) = SOCKET_ERROR then

raise ESocketException.Create(

'Невозможно установить сокет в режим прослушивания: ' +

GetErrorString);

WriteLn(OemString('Сервер успешно начал прослушивание порта '), Port);

...

// Основная часть сервера приведена в листинге 2.15

...

 except

on Е: ESocketException do

WriteLn(OemString(E.Message));

on E: Exception do

WriteLn(OemString('Неожиданное исключение ' + E.ClassName +

' с сообщением ' + E.Message));

 end;

end.

Основная часть кода сервера — это два цикла, один из которых вложен в другой (листинг 2.15). Перед внешним циклом сервер создает сокет и переводит его в режим прослушивания, и внешний цикл начинается с вызова функции

accept
. Завершение
accept
указывает на подключение клиента. После этого начинается внутренний цикл, который состоит из получения сообщений от клиента, преобразования строки и отправки ответа. Внутренний цикл завершается, когда соединение разрывается либо самим клиентом, либо из-за ошибки в сети. После этого управление вновь передается на начало внешнего цикла, т.е. на
accept
, и сервер может принять подключение другого клиента (или повторное подключение того же клиента).

Листинг 2.15. Основная часть сервера SimplestServer

// Начало цикла подключения и общения с клиентом

repeat

 ClientSockAddrLen := SizeOf(ClientSockAddr);

 // Принимаем подключившегося клиента. Для общения с ним создается новый

 // сокет, дескриптор которого помещается в ClientSocket.

 ClientSocket :=

accept(MainSocket, @ClientSockAddr, @ClientSockAddrLen);

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

Часовая башня

Щерба Наталья Васильевна
3. Часодеи
Фантастика:
фэнтези
9.43
рейтинг книги
Часовая башня

Попаданка в Измену или замуж за дракона

Жарова Анита
Любовные романы:
любовно-фантастические романы
6.25
рейтинг книги
Попаданка в Измену или замуж за дракона

На границе империй. Том 9. Часть 3

INDIGO
16. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 3

Жена на пробу, или Хозяйка проклятого замка

Васина Илана
Фантастика:
попаданцы
фэнтези
5.00
рейтинг книги
Жена на пробу, или Хозяйка проклятого замка

Ваше Сиятельство

Моури Эрли
1. Ваше Сиятельство
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Ваше Сиятельство

Восход. Солнцев. Книга I

Скабер Артемий
1. Голос Бога
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Восход. Солнцев. Книга I

Инвестиго, из медика в маги

Рэд Илья
1. Инвестиго
Фантастика:
фэнтези
городское фэнтези
попаданцы
5.00
рейтинг книги
Инвестиго, из медика в маги

Надуй щеки!

Вишневский Сергей Викторович
1. Чеболь за партой
Фантастика:
попаданцы
дорама
5.00
рейтинг книги
Надуй щеки!

Случайная свадьба (+ Бонус)

Тоцка Тала
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Случайная свадьба (+ Бонус)

Газлайтер. Том 5

Володин Григорий
5. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 5

Мастер Разума III

Кронос Александр
3. Мастер Разума
Фантастика:
героическая фантастика
попаданцы
аниме
5.25
рейтинг книги
Мастер Разума III

Наследник 2

Шимохин Дмитрий
2. Старицкий
Фантастика:
попаданцы
альтернативная история
фэнтези
5.75
рейтинг книги
Наследник 2

Неучтенный. Дилогия

Муравьёв Константин Николаевич
Неучтенный
Фантастика:
боевая фантастика
попаданцы
7.98
рейтинг книги
Неучтенный. Дилогия

Светлая тьма. Советник

Шмаков Алексей Семенович
6. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Светлая тьма. Советник