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

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

Жанры

О чём не пишут в книгах по 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. Долго и Несчастливо
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Жалкая

Беглец

Бубела Олег Николаевич
1. Совсем не герой
Фантастика:
фэнтези
попаданцы
8.94
рейтинг книги
Беглец

Академия проклятий. Книги 1 - 7

Звездная Елена
Академия Проклятий
Фантастика:
фэнтези
8.98
рейтинг книги
Академия проклятий. Книги 1 - 7

Измена. Верни мне мою жизнь

Томченко Анна
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Верни мне мою жизнь

Измена

Рей Полина
Любовные романы:
современные любовные романы
5.38
рейтинг книги
Измена

Гардемарин Ее Величества. Инкарнация

Уленгов Юрий
1. Гардемарин ее величества
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
фантастика: прочее
5.00
рейтинг книги
Гардемарин Ее Величества. Инкарнация

Сердце для стража

Каменистый Артем
5. Девятый
Фантастика:
фэнтези
боевая фантастика
9.20
рейтинг книги
Сердце для стража

Черный Маг Императора 11

Герда Александр
11. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Черный Маг Императора 11

Имя нам Легион. Том 3

Дорничев Дмитрий
3. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 3

Жена фаворита королевы. Посмешище двора

Семина Дия
Фантастика:
фэнтези
5.00
рейтинг книги
Жена фаворита королевы. Посмешище двора

Как я строил магическую империю 5

Зубов Константин
5. Как я строил магическую империю
Фантастика:
попаданцы
аниме
фантастика: прочее
фэнтези
5.00
рейтинг книги
Как я строил магическую империю 5

Блуждающие огни 2

Панченко Андрей Алексеевич
2. Блуждающие огни
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
альтернативная история
фэнтези
5.00
рейтинг книги
Блуждающие огни 2

Ратник

Ланцов Михаил Алексеевич
3. Помещик
Фантастика:
альтернативная история
7.11
рейтинг книги
Ратник

Маленькая слабость Дракона Андреевича

Рам Янка
1. Танцы на углях
Любовные романы:
современные любовные романы
эро литература
5.25
рейтинг книги
Маленькая слабость Дракона Андреевича