СТА 3/2018
ки к определённому IP-адресу функция SysSockBind() ссыла- ется на структуру SOCKADDRESS , в которой хранится задан- ный адрес сокета для привязки. Адрес сокета сервера задаётся один раз при инициализации (листинг 2). Переменная serverAddress имеет тип SOCKADDRESS . При инициализации необходимо выбрать семейство прото- колов, указать IP-адрес (записанный в виде текстовой пере- менной типа STRING, например, ’10.0.0.100’) и номер порта (переменная типа WORD, например, 503). После этого вызывается функция SysSockBind() , которая привязывает сокет к данному адресу (листинг 3). При успешной привязке к адресу функция SysSockListen() включает прослушивание входящих соединений (ожидание подключений клиентов к серверу). Функцией SysSockListen() также определяется максимальное количество подключений к серверу (листинг 4). Например, если максимальное количе- ство подключений равно 3 и все три клиента уже подключи- лись к серверу, то четвёртому будет отказано в подключении. Как только сервер включает режим прослушивания, он пе- реходит в рабочий режим и ждёт входящие соединения от клиентов. Когда клиент подключается к сокету сервера, с по- мощью функции SysSockAccept() создаётся системный иден- тификатор клиентского сокета hClientSocket и соединение считается открытым (листинг 5). Сообщения принимаются серверным сокетом с помощью функции SysSockRecv() . В данной функции задаётся указатель на переменную, куда будут сохраняться принимаемые со- общения (листинг 6). После приёма сообщений сервер может отправить ответ. Это осуществляется с помощью функции SysSockSend() . В данной функции задаётся указатель на переменную, в которой хра- нятся отправляемые данные (листинг 7). После успешных приёма и передачи данных возможны не- сколько вариантов поведения программы. 1. Программа может закрыть клиентское соединение. В этом случае в следующих циклах программы сервер будет ожи- дать подключения с новым клиентом. Такой режим работы не является эффективным, так как контроллеру придётся во время каждого цикла закрывать клиентское соединение и подключать нового клиента (или того же самого, что и в предыдущем цикле). 2. Программа может не закрывать клиентский сокет, а со- хранить установленное соединение. В этом случае, один раз установив соединение, клиент будет постоянно от- правлять и получать данные от сервера. Такой режим рабо- ты более эффективный, но может возникнуть ситуа- ция, когда все клиентские соединения будут заняты и новый клиент не сможет подключиться к серверу. Решить данную ситуацию можно различными способами. Один из вариантов – наблюдать за последним временем актив- ности клиентских сокетов и отключать самое старое соеди- нение в случае, если в очереди обнаружился новый клиент (рис. 7). В рабочем режиме серверный сокет всегда остаётся от- крытым. Закрытие серверного сокета может происходить при внешнем событии или при возникновении критических ошибок. Ошибки при создании и работе сокетов отображаются в си- стемном идентификаторе result , который имеет тип структуры RTS_IEC_RESULT . Обозначение кодов ошибок описано в си- стемной библиотеке CmpErrors Interfaces в глобальных кон- стантах Errors (рис. 8). Закрывает сокетное соединение функция SysSockClose() (листинг 8). В ЗАПИСНУЮ КНИЖК У ИНЖЕ Н Е РА СТА 3/2018 83 www.cta.ru Рис. 7. Обработка подключения нового клиента Рис. 8. Расшифровка кодов ошибок работы сокетов Cервер Клиент 1 Time1 Клиент 2 Time2 Клиент 3 Time3 MIN (Time1, Time2, Time3) Очередь на подключение Поиск самого старого соединения Самое старое соединение разрывается, и новый клиент занимает это соединение Время последней активности клиента Клиент 4
RkJQdWJsaXNoZXIy MTQ4NjUy