- Отправка Push-уведомлений
- Отправка уведомлений по электронной почте
- Отправка файлов на сервер FTP
- Обмен данными с веб-сервером по протоколу HTTP/HTTPS
- Установление и разрыв соединения сетевого сокета
- Проверка состояния сокета
- Настройка таймаутов передачи и приема данных сокетами
- Чтение, запись данных по незащищенному сокет-соединению
- Подготовка защищенного сокет-соединения
- Чтение и запись данных по защищенному сокет-соединению
Установление и разрыв соединения сетевого сокета
В предыдущих разделах мы познакомились с высокоуровневыми сетевыми функциями MQL5: каждая из них предоставляет поддержку прикладному протоколу конкретной направленности. Например, SMTP — для отправки электронной почты (SendMail), FTP — для передачи файлов (SendFTP) или HTTP — для получения веб-документов (WebRequest). Все упомянутые стандарты опираются на более низкий, транспортный уровень TCP (Transmission Control Protocol). Он не последний в иерархии — есть и более низкие, но здесь мы не станем их касаться.
Стандартная реализация прикладных протоколов скрывает внутри много технических нюансов и освобождает программиста от лишних часов рутинного следования спецификациям. Однако, она не обладает гибкостью, не учитывает расширенные возможности, заложенные в стандарты. Поэтому иногда требуется запрограммировать сетевое взаимодействие на уровне TCP — на уровне сокетов.
Сокет можно рассматривать как аналог файла на диске: сокет тоже описывается целочисленным дескриптором, по которому можно читать или записывать данные, но происходит это в распределенной сетевой инфраструктуре. В отличие от файлов, количество сокетов на компьютере ограничено, и потому дескриптор сокета нужно заранее запросить у системы, прежде чем связать его с сетевым ресурсом (адресом, URL). Также заранее скажем, что доступ к информации через сокет — поточный, то есть нельзя "перемотать" некий "указатель" на начало, как в файле.
Потоки записи и чтения не пересекаются, но могут влиять на будущие читаемые или записываемые данные, поскольку передаваемая информация часто трактуется серверами и клиентскими программами как управляющие команды. Когда поток содержит команды, а когда данные — определяют стандарты протоколов.
Для создания "пустого" дескриптора сокета в MQL5 предназначена функция SocketCreate.
int SocketCreate(uint flags = 0)
Единственный параметр зарезервирован на будущее для указания битовой комбинации флагов, определяющих режим работы сокета, однако в данный момент поддерживается только один флаг-заглушка — SOCKET_DEFAULT — он соответствует текущему режиму, и его можно не указывать. На системном уровне это эквивалентно сокету в блокирующем режиме (это может быть интересно специалистам в области сетевого программирования).
В случае успешного выполнения функция возвращает дескриптор сокета, а иначе — INVALID_HANDLE.
Из одной MQL-программы можно создать максимум 128 сокетов. При превышении лимита в _LastError записывается ошибка 5271 (ERR_NETSOCKET_TOO_MANY_OPENED).
После того как мы открыли сокет, его следует связать с сетевым адресом.
bool SocketConnect(int socket, const string server, uint port, uint timeout)
Функция SocketConnect выполняет подключение сокета к серверу по указанному адресу и порту (например, веб-сервера обычно работают на портах 80 или 443 для протоколов HTTP и HTTPS, соответственно, а SMTP — на порту 25). Адресом может выступать как доменное имя, так и IP-адрес.
Параметр timeout позволяет задать таймаут в миллисекундах для ожидания ответа сервера.
Функция возвращает признак успешного подключения (true) или ошибки (false). Код ошибки записывается в _LastError, например, 5272 (ERR_NETSOCKET_CANNOT_CONNECT).
Напоминаем: адрес для подключения должен быть добавлен в список разрешенных в настройках терминала (диалог Сервис -> Настройки -> Советники).
После завершения работы с сетью следует освободить сокет с помощью SocketClose.
bool SocketClose(const int socket)
Функция SocketClose закрывает сокет по его дескриптору, открытому ранее с помощью функции SocketCreate. Если для сокета ранее было создано соединение через SocketConnect, оно будет разорвано.
Функция также возвращает признак успеха (true) или ошибки (false). В частности, при передаче неверного дескриптора в _LastError записывается ошибка 5270 (ERR_NETSOCKET_INVALIDHANDLE).
Напоминаем, что все функции данного и последующих разделов запрещены в индикаторах: там попытка работать с сокетами приведет к ошибке 4014 (ERR_FUNCTION_NOT_ALLOWED, "Системная функция не разрешена для вызова").
Рассмотрим вводный пример — скрипт SocketConnect.mq5. Во входных параметрах можно задать адрес и порт сервера. Предполагается, что мы начнем тестирование с обычных веб-серверов, таких как mql5.com.
input string Server = "www.mql5.com";
|
В функции OnStart просто создадим сокет и свяжем его с сетевым ресурсом.
void OnStart()
|
Если все настройки в терминале сделаны правильно, и он подключен к Интернет, получим следующий "отчет".
Server=www.mql5.com / ok
|