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
, и сервер может принять подключение другого клиента (или повторное подключение того же клиента).
// Начало цикла подключения и общения с клиентом
repeat
ClientSockAddrLen := SizeOf(ClientSockAddr);
// Принимаем подключившегося клиента. Для общения с ним создается новый
// сокет, дескриптор которого помещается в ClientSocket.
ClientSocket :=
accept(MainSocket, @ClientSockAddr, @ClientSockAddrLen);
if ClientSocket = INVALID_SOCKET then
raise ESocketException.Create(