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

на главную

Жанры

О чём не пишут в книгах по 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);

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

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

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

Мастер 7

Чащин Валерий
7. Мастер
Фантастика:
фэнтези
боевая фантастика
попаданцы
технофэнтези
аниме
5.00
рейтинг книги
Мастер 7

Неудержимый. Книга XIV

Боярский Андрей
14. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга XIV

Все не случайно

Юнина Наталья
Любовные романы:
современные любовные романы
7.10
рейтинг книги
Все не случайно

Гром над Тверью

Машуков Тимур
1. Гром над миром
Фантастика:
боевая фантастика
5.89
рейтинг книги
Гром над Тверью

Идущий в тени 5

Амврелий Марк
5. Идущий в тени
Фантастика:
фэнтези
рпг
5.50
рейтинг книги
Идущий в тени 5

Кровь, золото и помидоры

Распопов Дмитрий Викторович
4. Венецианский купец
Фантастика:
альтернативная история
5.40
рейтинг книги
Кровь, золото и помидоры

Неудержимый. Книга VIII

Боярский Андрей
8. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
6.00
рейтинг книги
Неудержимый. Книга VIII

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

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

Пистоль и шпага

Дроздов Анатолий Федорович
2. Штуцер и тесак
Фантастика:
альтернативная история
8.28
рейтинг книги
Пистоль и шпага

Мастер 4

Чащин Валерий
4. Мастер
Фантастика:
героическая фантастика
боевая фантастика
попаданцы
5.00
рейтинг книги
Мастер 4

Темный Патриарх Светлого Рода 6

Лисицин Евгений
6. Темный Патриарх Светлого Рода
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Темный Патриарх Светлого Рода 6

Лорд Системы 14

Токсик Саша
14. Лорд Системы
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Лорд Системы 14

Падение Твердыни

Распопов Дмитрий Викторович
6. Венецианский купец
Фантастика:
попаданцы
альтернативная история
5.33
рейтинг книги
Падение Твердыни