{"id":353764,"date":"2024-05-20T22:34:40","date_gmt":"2024-05-20T22:34:40","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=353764"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=353764","title":{"rendered":"<span>\u0422\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0443\u0440<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h3>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0443\u0440?<\/h3>\n<p>\u042d\u0442\u043e \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0434\u0435\u043b\u0451\u043d \u043e\u0442\u00a0\u0441\u0435\u0442\u0438 \u0447\u0435\u0440\u0435\u0437 \u00ab\u0434\u0438\u043e\u0434\u00bb (\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u043e\u0434\u043d\u043e\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445). \u0418\u0437\u00a0\u043d\u0435\u0433\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435\u00a0\u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0445\u043e\u0434\u0438\u0442\u044c, \u0430\u00a0\u0432\u0445\u043e\u0434\u0438\u0442\u044c \u043c\u043e\u0436\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u00a0\u043e\u0434\u043d\u043e\u043c\u0443 \u043a\u0430\u043d\u0430\u043b\u0443, \u0441\u00a0\u043e\u0434\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0440\u0435\u0448\u0451\u043d\u043d\u043e\u0433 \u043e IP, \u043f\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u043c, \u0441\u0442\u0440\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u043c \u043f\u043e\u0440\u0442\u0430\u043c.<\/p>\n<p>\u0420\u0430\u0437\u0440\u0435\u0448\u0451\u043d\u043d\u044b\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f IP \u0434\u0438\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0432\u044f\u0437\u0430\u043d \u0441 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u043a\u043e\u043d\u0442\u0443\u0440\u043e\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0435\u0442\u044c\u044e, \u043f\u043e\u0434\u043d\u044f\u0442\u043e\u0439 \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u043f\u0430\u0440\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432.<\/p>\n<h3>\u0417\u0430\u0447\u0435\u043c \u043e\u043d \u0442\u0430\u043a\u043e\u0439 \u043d\u0443\u0436\u0435\u043d? \u0414\u043b\u044f \u0447\u0435\u0433\u043e \u0434\u0435\u043b\u0430\u044e\u0442 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0443\u0440?<\/h3>\n<p>\u041e\u0431\u044b\u0447\u043d\u043e, \u044d\u0442\u043e \u043a\u043e\u043f\u0438\u044f \u0440\u0430\u0431\u043e\u0447\u0435\u0439 \u0441\u0440\u0435\u0434\u044b, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u0443\u044e, \u043f\u043e\u043c\u0438\u043c\u043e \u043e\u0431\u0449\u0435\u0433\u043e, \u043f\u043e\u043c\u0435\u0449\u0430\u044e\u0442 \u0442\u0430\u043a\u0436\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0441\u0442\u0440\u043e\u0433\u043e \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430\u043c\u0438 \u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0430\u043c\u0438. \u0417\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043b\u044e\u0434\u0438. \u0421\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0438 \u043f\u0440\u0438 \u043a\u0430\u043a\u0438\u0445 \u043e\u0431\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0430\u0445 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043a\u0438\u0434\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440, \u043a\u0440\u043e\u043c\u0435 \u043a\u0430\u043a \u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u043e\u043c \u0432\u0438\u0434\u0435 \u0438 \u043d\u0430 \u0431\u0443\u043c\u0430\u0436\u043d\u043e\u043c \u043d\u043e\u0441\u0438\u0442\u0435\u043b\u0435. \u041e\u043f\u044f\u0442\u044c \u0436\u0435 \u0441 \u0441\u043e\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u0435\u043c \u0432\u0441\u0435\u0445 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440.<\/p>\n<h3>\u041a\u0430\u043a \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435?<\/h3>\n<p>\u041f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0436\u0435\u0442 \u043b\u044e\u0431\u043e\u0439 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440 \u0432 \u0441\u0435\u0442\u0438. \u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u0434\u0438\u043e\u0434. \u0414\u0430\u043b\u0435\u0435 \u043e\u043d \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0443\u0436\u0435 \u043d\u0430 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0443\u0440. \u0412 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0434\u0438\u043e\u0434\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0451\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u0440\u0438\u0451\u043c\u0430 \u0430\u0434\u0440\u0435\u0441\u0430 \u0438 \u043f\u043e\u0440\u0442\u044b.<\/p>\n<p>\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 UDP, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0443 \u0431\u0435\u0437 \u043f\u043e\u0442\u0435\u0440\u044c. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0434\u043d\u043e \u0438 \u0442\u043e \u0436\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u043f\u043e\u0434\u0440\u044f\u0434 \u0441 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u043c\u0435\u0436\u0434\u0443 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044f\u043c\u0438. \u0422\u0430\u043a\u0436\u0435, \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u043d\u0435 \u0446\u0435\u043b\u0438\u043a\u043e\u043c, \u0430 \u0441 \u0440\u0430\u0437\u0431\u0438\u0432\u043a\u043e\u0439 \u043d\u0430 \u043f\u0430\u043a\u0435\u0442\u044b. \u041a\u0430\u0436\u0434\u044b\u0439 \u043f\u0430\u043a\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0444\u043e\u0440\u043c\u0438\u0442\u044c, \u0442\u0430\u043a \u0436\u0435 \u043a\u0430\u043a \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u043f\u0430\u043a\u0435\u0442\u0430\u0445, \u0447\u0442\u043e\u0431\u044b \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432. \u0411\u043b\u043e\u043a\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0445\u044d\u0448\u0430\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0446\u0435\u043b\u043e\u0441\u0442\u043d\u043e\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438.<\/p>\n<p>\u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u043d\u0430\u0434\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 5 \u0440\u0430\u0437) \u0441 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430\u043c\u0438 \u043c\u0435\u0436\u0434\u0443 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435\u0439 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0434\u043d\u0443 \u0441\u0435\u043a\u0443\u043d\u0434\u0443).<\/p>\n<h2>\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/h2>\n<p>\u0418\u0442\u0430\u043a, \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0445\u0435\u043b\u043f\u0435\u0440, \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0437\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0434\u0430\u043d\u043d\u044b\u0445. \u0414\u0430\u043b\u0435\u0435 \u0442\u0435\u0437\u0438\u0441\u043d\u043e&#8230;<\/p>\n<p>\u0414\u043b\u0438\u043d\u0430 \u043f\u0430\u043a\u0435\u0442\u0430<\/p>\n<pre><code class=\"php\">const SEND_BYTES_MAX = 1500;<\/code><\/pre>\n<p>\u0410\u0434\u0440\u0435\u0441 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438<\/p>\n<pre><code class=\"php\">public function __construct($host, $port)<\/code><\/pre>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0448\u0430\u0433\u043e\u0432<\/p>\n<pre><code class=\"php\">public function send($data) { $this->createSocket();  \/\/ \u043f\u043e\u0434\u043d\u044f\u0442\u044c \u0441\u043e\u043a\u0435\u0442 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0447\u0435\u0440\u0435\u0437 UDP $this->splitWithUnicode($data);  \/\/ \u0440\u0430\u0437\u0431\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u0431\u043b\u043e\u043a\u0438 $this->sendMetadata();  \/\/ \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 $this->sendSplits();  \/\/ \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0431\u043b\u043e\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 $this->sendEnding();  \/\/ \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 $this->closeSocket();  \/\/ \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u0441\u043e\u043a\u0435\u0442 }<\/code><\/pre>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u043e\u043a\u0435\u0442\u0430<\/p>\n<pre><code class=\"php\">protected function createSocket() { $this->socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); if ($this->socket === false) { $errorCode = socket_last_error(); $errorMessage = socket_strerror($errorCode); $this->logger->critical('\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u043a\u0435\u0442 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.', ['errorCode' => $errorCode, 'errorMessage' => $errorMessage]); throw new RuntimeException('\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u043a\u0435\u0442 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.'); } }<\/code><\/pre>\n<p>\u0420\u0430\u0437\u0431\u0438\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0431\u043b\u043e\u043a\u0438 \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438. \u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u043b\u0438\u043d\u0430 \u0431\u043b\u043e\u043a\u0430 \u0437\u0430\u0434\u0430\u0451\u0442\u0441\u044f \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u043e\u0439. \u041a\u0430\u0436\u0434\u044b\u0439 \u0431\u043b\u043e\u043a \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u0434\u043b\u0438\u043d\u044b \u0431\u0430\u0439\u0442. \u041a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430 \u043d\u0443\u0436\u043d\u0430 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0440\u0430\u0437\u0431\u0438\u0432\u043a\u0438 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438.<\/p>\n<p>\u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0444\u0443\u043d\u043a\u0446\u0438\u044f mb_str_split \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 PHP 7.4.<\/p>\n<pre><code class=\"php\">protected function splitWithUnicode($data) { $this->splits = []; $maxLength = self::SEND_BYTES_MAX \/ 2; $dataLength = mb_strlen($data, \"UTF-8\"); for ($i = 0; $i &lt; $dataLength; $i += $maxLength) { $this->splits[] = mb_substr($data, $i, $maxLength, \"UTF-8\"); } }<\/code><\/pre>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<pre><code class=\"php\">protected function sendMetadata() { $metadata = [ 'countSplits' => count($this->splits),  \/\/ \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0431\u043b\u043e\u043a\u043e\u0432 ]; if ($this->code) { $metadata['code'] = $this->code;  \/\/ \u043a\u043e\u0434 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 } if ($this->name) { $metadata['name'] = $this->name;  \/\/ \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0438\u043c\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430, \u0438\u043b\u0438 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u043b\u043e\u043a\u0430 } $this->sendDataWithHash(json_encode($metadata));  \/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c JSON-\u0441\u0442\u0440\u043e\u043a\u0443 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 }<\/code><\/pre>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u0445\u044d\u0448\u0435\u043c. 8 \u0431\u0430\u0439\u0442 \u0432\u043f\u0435\u0440\u0435\u0434\u0438 \u0431\u043b\u043e\u043a\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0445\u044d\u0448 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u043d\u0430\u0447\u0430\u043b\u043e \u0431\u043b\u043e\u043a\u0430.<\/p>\n<pre><code class=\"php\">protected function sendDataWithHash($data) { $hash = hash('crc32', $data); $hashAndData = $hash . $data; $this->sendData($hashAndData); }<\/code><\/pre>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<pre><code class=\"php\">protected function sendData($data) { $sent = socket_sendto($this->socket, $data, strlen($data), 0, $this->host, $this->port); if ($sent === false) { $errorCode = socket_last_error(); $errorMessage = socket_strerror($errorCode); $this->logger->warning('\u0414\u0430\u043d\u043d\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 \u0441\u043e\u043a\u0435\u0442 \u043d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u044b.', ['errorCode' => $errorCode, 'errorMessage' => $errorMessage]); } time_sleep_until(microtime(true) + .001);  \/\/ \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430 \u043c\u0435\u0436\u0434\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430\u043c\u0438 \u0431\u043b\u043e\u043a\u043e\u0432 \u043f\u043e \u0441\u0435\u0442\u0438. \u041f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f 1,5 \u043c\u0435\u0433\u0430\u0431\u0430\u0439\u0442\u0430 \u0437\u0430 \u043e\u0434\u043d\u0443 \u0441\u0435\u043a\u0443\u043d\u0434\u0443. }<\/code><\/pre>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0431\u043b\u043e\u043a\u043e\u0432<\/p>\n<pre><code class=\"php\">protected function sendSplits() { foreach ($this->splits as $split) { $this->sendDataWithHash($split); } }<\/code><\/pre>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0441\u0442\u0440\u043e\u043a\u0438 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f<\/p>\n<pre><code class=\"php\">protected function sendEnding() { $endingString = chr(0); $this->sendData($endingString); }<\/code><\/pre>\n<p>\u0417\u0430\u043a\u0440\u044b\u0442\u0438\u0435 \u0441\u043e\u043a\u0435\u0442\u0430<\/p>\n<pre><code class=\"php\">protected function closeSocket() { socket_close($this->socket); }<\/code><\/pre>\n<p>\u0412\u0435\u0441\u044c \u043a\u043b\u0430\u0441\u0441 \u043f\u043e\u0434 \u0441\u043f\u043e\u0439\u043b\u0435\u0440\u043e\u043c.<\/p>\n<details class=\"spoiler\">\n<summary>Hidden text<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"php\">&lt;?php  namespace Application\\Workers\\Udp;  use Application\\Logger\\AppLogger; use RuntimeException;  \/**  * \u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 UDP.  *\/ class UdpSender {     const SEND_BYTES_MAX = 1500;      \/** @var string *\/     protected $host;      \/** @var integer *\/     protected $port;      \/** @var AppLogger *\/     protected $logger;      \/** @var integer|string *\/     protected $code;      \/** @var string *\/     protected $name;      \/** @var resource *\/     protected $socket;      \/** @var array *\/     protected $splits;      \/**      * @param string $host      * @param integer $port      *\/     public function __construct($host, $port)     {         $this->host = $host;         $this->port = $port;         $this->logger = new AppLogger('Request');     }      \/**      * \u041f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u043a\u043e\u0434 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430.      *      * @param integer|string $code      * @return UdpSender      *\/     public function withCode($code)     {         $this->code = $code;         return $this;     }      \/**      * \u041f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430.      *      * @param string $name      * @return UdpSender      *\/     public function withName($name)     {         $this->name = $name;         return $this;     }      \/**      * \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435.      *      * @param string $data      * @return void      *\/     public function send($data)     {         $this->createSocket();         $this->splitWithUnicode($data);         $this->sendMetadata();         $this->sendSplits();         $this->sendEnding();         $this->closeSocket();     }      \/**      * \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u043a\u0435\u0442 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.      *      * @return void      *\/     protected function createSocket()     {         $this->socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);         if ($this->socket === false) {             $errorCode = socket_last_error();             $errorMessage = socket_strerror($errorCode);             $this->logger->critical('\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u043a\u0435\u0442 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.', ['errorCode' => $errorCode, 'errorMessage' => $errorMessage]);             throw new RuntimeException('\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u043a\u0435\u0442 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.');         }     }      \/**      * \u0420\u0430\u0437\u0431\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u043d\u0430 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0441 \u0443\u0447\u0451\u0442\u043e\u043c Unicode.      *      * @param string $data      * @return void      *\/     protected function splitWithUnicode($data)     {         $this->splits = [];         $maxLength = self::SEND_BYTES_MAX \/ 2;         $dataLength = mb_strlen($data, \"UTF-8\");         for ($i = 0; $i &lt; $dataLength; $i += $maxLength) {             $this->splits[] = mb_substr($data, $i, $maxLength, \"UTF-8\");         }     }      \/**      * \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435.      *      * @return void      *\/     protected function sendMetadata()     {         $metadata = [             'countSplits' => count($this->splits),         ];         if ($this->code) {             $metadata['code'] = $this->code;         }         if ($this->name) {             $metadata['name'] = $this->name;         }         $this->logger->debug('\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445.', ['metadata' => $metadata]);         $this->sendDataWithHash(json_encode($metadata));     }      \/**      * \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0441 \u0445\u044d\u0448\u0435\u043c.      *      * @param string $data      * @return void      *\/     protected function sendDataWithHash($data)     {         $hash = hash('crc32', $data);         $hashAndData = $hash . $data;         $this->sendData($hashAndData);     }      \/**      * \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435.      *      * @param string $data      * @return void      *\/     protected function sendData($data)     {         $sent = socket_sendto($this->socket, $data, strlen($data), 0, $this->host, $this->port);         if ($sent === false) {             $errorCode = socket_last_error();             $errorMessage = socket_strerror($errorCode);             $this->logger->warning('\u0414\u0430\u043d\u043d\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 \u0441\u043e\u043a\u0435\u0442 \u043d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u044b.', ['errorCode' => $errorCode, 'errorMessage' => $errorMessage]);         }         time_sleep_until(microtime(true) + .001);     }      \/**      * \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0447\u0430\u0441\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.      *      * @return void      *\/     protected function sendSplits()     {         $this->logger->debug('\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 \u0441\u043e\u043a\u0435\u0442.', ['countSplits' => count($this->splits)]);         foreach ($this->splits as $split) {             $this->sendDataWithHash($split);         }     }      \/**      * \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f.      *      * @return void      *\/     protected function sendEnding()     {         $endingString = chr(0);         $this->sendData($endingString);     }      \/**      * \u0417\u0430\u043a\u0440\u044b\u0442\u044c \u0441\u043e\u043a\u0435\u0442.      *      * @return void      *\/     protected function closeSocket()     {         socket_close($this->socket);     }  }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<h2>\u041f\u0440\u0438\u043d\u044f\u0442\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0443\u0440\u0430<\/h2>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441\u0435\u0440\u0432\u0438\u0441. \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043d\u0435 \u0432\u0445\u043e\u0434\u0438\u0442 \u0432 \u0434\u0430\u043d\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e. \u0415\u0441\u043b\u0438 \u043a\u043e\u0440\u043e\u0442\u043a\u043e, \u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u0434\u0435\u043c\u043e\u043d, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u041e\u0421. \u041e\u043d \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043d\u0430\u0448 PHP-\u0441\u043a\u0440\u0438\u043f\u0442, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0439 \u0437\u0430 \u043f\u0440\u0438\u0451\u043c \u0434\u0430\u043d\u043d\u044b\u0445. \u041f\u0440\u0438 \u043f\u0430\u0434\u0435\u043d\u0438\u0438 PHP-\u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0434\u0435\u043c\u043e\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0441\u0435\u0440\u0432\u0438\u0441.<br \/>\u0421\u043a\u0440\u0438\u043f\u0442 \u0446\u0438\u043a\u043b\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u043e\u0441\u043b\u0443\u0448\u0438\u0432\u0430\u0435\u0442 \u0441\u043e\u043a\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430<\/p>\n<pre><code class=\"php\">public function executeService() { $this->connectToSocket(); while (true) {  \/\/ \u0412\u0435\u0447\u043d\u044b\u0439 \u0446\u0438\u043a\u043b $this->receiveData();  \/\/ \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 $this->defineData();  \/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 } }<\/code><\/pre>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u0441\u043e\u043a\u0435\u0442\u0443 \u043d\u0430 \u0430\u0434\u0440\u0435\u0441 \u0438 \u043f\u043e\u0440\u0442<\/p>\n<pre><code class=\"php\">$this->socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); if (@socket_bind($this->socket, $host, $port) === false) {     \/\/ ... \u043e\u0448\u0438\u0431\u043a\u0430 exit(\"Failed to bind socket on $host:$port, $errorCode: $errorMessage\" . PHP_EOL);  \/\/ \u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430, \u0447\u0442\u043e\u0431\u044b \u0441\u0435\u0440\u0432\u0438\u0441 \u0441\u043c\u043e\u0433 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c\u0441\u044f }<\/code><\/pre>\n<p>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"php\">protected function receiveData() { @socket_recvfrom($this->socket, $this->buffer, 52428800, 0, $ip, $port); $this->address = \"$ip:$port\"; $this->logger->debug('\u041f\u0440\u0438\u043d\u044f\u0442\u044b \u0434\u0430\u043d\u043d\u044b\u0435', ['address' => $this->address, 'length' => strlen($this->buffer)]); }<\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<pre><code class=\"php\">protected function defineData() { if ($this->checkForFirstBlock()) {  \/\/ \u041d\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 ? $this->initializeTransmitting();  \/\/ \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u043f\u0440\u0438\u0451\u043c\u0430 \u0441 \u044d\u0442\u043e\u0433\u043e \u0430\u0434\u0440\u0435\u0441\u0430 } elseif ($this->checkReceiveComplete()) {  \/\/ \u041a\u043e\u043d\u0435\u0446 \u0434\u0430\u043d\u043d\u044b\u0445 ? $this->completeReceive();  \/\/ \u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 $this->resetFile();  \/\/ \u0421\u0431\u0440\u043e\u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u043f\u0440\u0438\u0451\u043c\u0430 \u0441 \u044d\u0442\u043e\u0433\u043e \u0430\u0434\u0440\u0435\u0441\u0430 } else { $this->addSection();  \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043d\u044f\u0442\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430 } }<\/code><\/pre>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u0431\u043b\u043e\u043a \u043a\u0440\u043e\u043c\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u044e\u0449\u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0445\u044d\u0448, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c \u043e\u0441\u0442\u0430\u0432\u0448\u0435\u0439\u0441\u044f \u043f\u0440\u0438\u043d\u044f\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0445. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0441\u043e\u0431\u043b\u044e\u0434\u0430\u0435\u0442\u0441\u044f \u0446\u0435\u043b\u043e\u0441\u0442\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u043d\u044f\u0442\u0438\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430.<\/p>\n<p>\u0421\u0430\u043c\u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043f\u0435\u0440\u0432\u043e\u043c, \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u043e\u043c \u0431\u043b\u043e\u043a\u0435, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0445 \u0431\u043b\u043e\u043a\u043e\u0432. \u0422\u0430\u043a\u0436\u0435 \u0432\u0435\u0434\u0451\u0442\u0441\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432, \u043f\u0440\u0438\u043d\u044f\u0442\u044b\u0445 \u0441 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438.<\/p>\n<p>\u0417\u0430\u0432\u0435\u0440\u0448\u0430\u044e\u0449\u0438\u0439 \u0431\u043b\u043e\u043a \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0431\u0430\u0439\u0442\u0430 \u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0443\u043b\u0435\u0432\u043e\u0439 \u0441\u0438\u043c\u0432\u043e\u043b (\u0441 \u043a\u043e\u0434\u043e\u043c 0).<\/p>\n<p>\u041a\u0430\u043a\u0438\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b?<\/p>\n<ul>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u0434\u0443\u0442 \u0431\u0438\u0442\u044b\u0435, \u0442\u043e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u043d\u0435 \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0451\u0442. \u0412\u0441\u0435 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u043d\u044b, \u043a\u0430\u043a \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435. \u0411\u043b\u043e\u043a \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0442\u0430\u043a \u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0435 \u0432\u0441\u0435 \u0431\u043b\u043e\u043a\u0438 \u043f\u0440\u0438\u0448\u043b\u0438 \u0438\u043b\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u043b\u043e\u043a\u0438 \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u044b \u0438\u0437-\u0437\u0430 \u043d\u0435\u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044f \u0445\u044d\u0448\u0435\u0439, \u0442\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u0438\u043d\u044f\u0442\u044b\u0445 \u0431\u043b\u043e\u043a\u043e\u0432 \u043d\u0435 \u0441\u043e\u0439\u0434\u0451\u0442\u0441\u044f \u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0451\u0442 \u0441 \u043d\u0435\u0443\u0434\u0430\u0447\u0435\u0439.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u044e\u0449\u0438\u0439 \u0441\u0438\u043c\u0432\u043e\u043b \u043d\u0435 \u043f\u0440\u0438\u0434\u0451\u0442, \u0442\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043b\u0435\u043f\u043b\u0435\u043d\u0430 \u043a \u0434\u0430\u043d\u043d\u043e\u0439 \u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u0441\u044f \u043d\u0435\u0443\u0434\u0430\u0447\u0435\u0439. \u0412 \u043d\u0435\u0439 \u043e\u043f\u044f\u0442\u044c \u0436\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0431\u043b\u043e\u043a\u043e\u0432 \u043d\u0435 \u0441\u043e\u0439\u0434\u0451\u0442\u0441\u044f.<\/p>\n<\/li>\n<li>\n<p>\u0421 \u043e\u0434\u043d\u043e\u0433\u043e \u0430\u0434\u0440\u0435\u0441\u0430 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e. \u041d\u043e \u0435\u0441\u043b\u0438 \u0442\u0430\u043a\u043e\u0435 \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0451\u0442, \u0442\u043e \u0431\u043b\u043e\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u043a\u0430\u0436\u0443\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u043f\u0443\u0442\u0430\u043d\u044b \u0438 \u0438\u0445 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0451\u0442 \u0441 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u0447\u0442\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043a \u043e\u0442\u043a\u0430\u0437\u0443 \u043e\u0442 \u043f\u0440\u0438\u0451\u043c\u0430 \u043e\u0431\u0435\u0438\u0445 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439. \u041e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u0438\u0451\u043c \u0441 \u0440\u0430\u0437\u043d\u044b\u0445 \u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c.<\/p>\n<\/li>\n<\/ul>\n<p>\u0417\u0430\u0432\u0435\u0440\u0448\u0430\u044e\u0449\u0438\u0439 \u0431\u043b\u043e\u043a \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u0432\u0441\u0435\u0445 \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044e \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 \u043a\u043b\u0430\u0441\u0441\u0430 \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d \u043d\u0438\u0436\u0435. \u0412 \u043d\u0451\u043c \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u044b \u043c\u0435\u0442\u043e\u0434\u044b, \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0437\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0439 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>Hidden text<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"php\">&lt;?php  namespace Application\\Services\\ReceiveFiles;  use Application\\Logger\\AppLogger; use RuntimeException;  class ReceiveFiles {      const METADATA_KEYS_REQUIRED = ['name', 'code', 'countSplits'];      \/** @var AppLogger *\/     protected $logger;      \/** @var array *\/     protected $config;      \/** @var resource *\/     protected $socket;      \/** @var string *\/     protected $buffer;      \/** @var string *\/     protected $address;      \/** @var array *\/     protected $splits = [];      \/** @var array *\/     protected $metadata = [];      \/** @var array *\/     protected $hasErrors = [];      public function initialize(array $config = [])     {         $this->logger = new AppLogger('Request');     }      public function initConfig(array $config)     {         $this->config = $config;     }      public function executeService()     {         $this->connectToSocket();         while (true) {             $this->receiveData();             $this->defineData();         }     }      protected function connectToSocket()     {         $host = $this->config['host'];         $port = $this->config['port'];         $this->logger->debug('\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u0441\u043e\u043a\u0435\u0442\u0443.', ['host' => $host, 'port' => $port]);         $this->socket = @socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);         if (@socket_bind($this->socket, $host, $port) === false) {             $errorCode = socket_last_error();             $errorMessage = socket_strerror($errorCode);             $this->logger->critical('\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043a \u0441\u043e\u043a\u0435\u0442\u0443.', ['host' => $host, 'port' => $port, 'code' => $errorCode, 'message' => $errorMessage]);             exit(\"Failed to bind socket on $host:$port, $errorCode: $errorMessage\" . PHP_EOL);         }         $this->logger->info('\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043e \u043a \u0441\u043e\u043a\u0435\u0442\u0443.', ['host' => $host, 'port' => $port]);     }      protected function receiveData()     {         @socket_recvfrom($this->socket, $this->buffer, 52428800, 0, $ip, $port);         $this->address = \"$ip:$port\";         $this->logger->debug('\u041f\u0440\u0438\u043d\u044f\u0442\u044b \u0434\u0430\u043d\u043d\u044b\u0435', ['address' => $this->address, 'length' => strlen($this->buffer)]);     }      protected function defineData()     {         if ($this->checkForFirstBlock()) {             $this->initializeTransmitting();         } elseif ($this->checkReceiveComplete()) {             $this->completeReceive();             $this->resetFile();         } else {             $this->addSection();         }     }      protected function checkForFirstBlock()     {         $firstBlock = !isset($this->splits[$this->address]);         if ($firstBlock) {             $this->logger->debug('\u041f\u043e\u043b\u0443\u0447\u0435\u043d \u043f\u0435\u0440\u0432\u044b\u0439 \u0431\u043b\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445.', ['address' => $this->address]);         }         return $firstBlock;     }      protected function initializeTransmitting()     {         $this->splits[$this->address] = [];         $data = $this->fetchDataFromBufferWithHash();         $metadata = json_decode($data, true);         if (!isset($metadata)) {             $this->logger->error('\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0438\u0437\u0432\u043b\u0435\u0447\u044c \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430.', ['address' => $this->address]);             return;         }          foreach (self::METADATA_KEYS_REQUIRED as $checkKey) {             if (empty($metadata[$checkKey])) {                 $this->logger->error('\u041e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u043a\u043b\u044e\u0447 \u0432 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445.', ['keyAbsent' => $checkKey, 'metadata' => $metadata]);             }         }          $this->logger->debug('\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u044b \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435.', ['address' => $this->address, 'metadata' => $metadata]);         $this->metadata[$this->address] = $metadata;     }      protected function fetchDataFromBufferWithHash()     {         $hash = substr($this->buffer, 0, 8);         $data = substr($this->buffer, 8);         if ($hash !== hash('crc32', $data)) {             $this->logger->debug('\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u0430\u044f \u0441\u0443\u043c\u043c\u0430 \u0431\u043b\u043e\u043a\u0430 \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442!', ['address' => $this->address]);             $this->hasErrors[$this->address] = true;             return false;         }         return $data;     }      protected function checkReceiveComplete()     {         if (!isset($this->metadata[$this->address])) {             return false;         }         $complete = ord($this->buffer) === 0 &amp;&amp; strlen($this->buffer) === 1;         if ($complete) {             $this->logger->debug('\u041f\u043e\u043b\u0443\u0447\u0435\u043d \u043a\u043e\u0434 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043b\u0430.', ['address' => $this->address]);         }         return $complete;     }      protected function completeReceive()     {         if ($this->hasErrors[$this->address]) {             $this->logger->info('\u041e\u0442\u043c\u0435\u043d\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0438\u0437-\u0437\u0430 \u043e\u0448\u0438\u0431\u043e\u043a.', ['address' => $this->address, 'metadata' => $this->metadata[$this->address]]);             return;         }          if ($this->metadata[$this->address]['countSplits'] !== count($this->splits[$this->address])) {             $this->logger->info('\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u0438\u043d\u044f\u0442\u044b\u0445 \u0441\u0435\u043a\u0446\u0438\u0439 \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442.', ['address' => $this->address, 'countSplits' => count($this->splits[$this->address]), 'countExpected' => $this->metadata[$this->address]['countSplits']]);             return;         }          $this->logger->info('\u0417\u0430\u0432\u0435\u0440\u0448\u0451\u043d \u043f\u0440\u0438\u0451\u043c \u0444\u0430\u0439\u043b\u0430.', ['address' => $this->address, 'metadata' => $this->metadata[$this->address]]);         \/\/ ... \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u044b \u0441\u0442\u0440\u043e\u043a\u0438. \u041f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445: implode('', $this->splits[$this->address])     }      protected function resetFile()     {         unset($this->splits[$this->address]);         unset($this->metadata[$this->address]);         unset($this->hasErrors[$this->address]);     }      protected function addSection()     {         $data = $this->fetchDataFromBufferWithHash();         if ($data) {             $this->splits[$this->address][] = $data;             $this->logger->debug('\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u0431\u043b\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445.', ['address' => $this->address, 'iterator' => count($this->splits[$this->address])]);         }     }  }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>P.S. \u0417\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u043c\u0438 \u0441\u0442\u0430\u0442\u044c\u0438 \u043e\u0441\u0442\u0430\u043b\u0438\u0441\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u043d\u044f\u0442\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0439 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>P.P.S. \u041d\u0435 \u0441\u0443\u0434\u0438\u0442\u0435 \u043e\u0447\u0435\u043d\u044c \u0441\u0442\u0440\u043e\u0433\u043e. \u042d\u0442\u043e \u043c\u043e\u044f \u0442\u0440\u0435\u0442\u044c\u044f \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u0432\u044b\u0440\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u0437 \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u044b.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/758338\/\"> https:\/\/habr.com\/ru\/articles\/758338\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h3>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0443\u0440?<\/h3>\n<p>\u042d\u0442\u043e \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0434\u0435\u043b\u0451\u043d \u043e\u0442\u00a0\u0441\u0435\u0442\u0438 \u0447\u0435\u0440\u0435\u0437 \u00ab\u0434\u0438\u043e\u0434\u00bb (\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u043e\u0434\u043d\u043e\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445). \u0418\u0437\u00a0\u043d\u0435\u0433\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435\u00a0\u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0445\u043e\u0434\u0438\u0442\u044c, \u0430\u00a0\u0432\u0445\u043e\u0434\u0438\u0442\u044c \u043c\u043e\u0436\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u00a0\u043e\u0434\u043d\u043e\u043c\u0443 \u043a\u0430\u043d\u0430\u043b\u0443, \u0441\u00a0\u043e\u0434\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0440\u0435\u0448\u0451\u043d\u043d\u043e\u0433 \u043e IP, \u043f\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u043c, \u0441\u0442\u0440\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u043c \u043f\u043e\u0440\u0442\u0430\u043c.<\/p>\n<p>\u0420\u0430\u0437\u0440\u0435\u0448\u0451\u043d\u043d\u044b\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f IP \u0434\u0438\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0432\u044f\u0437\u0430\u043d \u0441 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u043a\u043e\u043d\u0442\u0443\u0440\u043e\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0435\u0442\u044c\u044e, \u043f\u043e\u0434\u043d\u044f\u0442\u043e\u0439 \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u043f\u0430\u0440\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432.<\/p>\n<h3>\u0417\u0430\u0447\u0435\u043c \u043e\u043d \u0442\u0430\u043a\u043e\u0439 \u043d\u0443\u0436\u0435\u043d? \u0414\u043b\u044f \u0447\u0435\u0433\u043e \u0434\u0435\u043b\u0430\u044e\u0442 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0443\u0440?<\/h3>\n<p>\u041e\u0431\u044b\u0447\u043d\u043e, \u044d\u0442\u043e \u043a\u043e\u043f\u0438\u044f \u0440\u0430\u0431\u043e\u0447\u0435\u0439 \u0441\u0440\u0435\u0434\u044b, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u0443\u044e, \u043f\u043e\u043c\u0438\u043c\u043e \u043e\u0431\u0449\u0435\u0433\u043e, \u043f\u043e\u043c\u0435\u0449\u0430\u044e\u0442 \u0442\u0430\u043a\u0436\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0441\u0442\u0440\u043e\u0433\u043e \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430\u043c\u0438 \u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0430\u043c\u0438. \u0417\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043b\u044e\u0434\u0438. \u0421\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0438 \u043f\u0440\u0438 \u043a\u0430\u043a\u0438\u0445 \u043e\u0431\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0430\u0445 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043a\u0438\u0434\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440, \u043a\u0440\u043e\u043c\u0435 \u043a\u0430\u043a \u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u043e\u043c \u0432\u0438\u0434\u0435 \u0438 \u043d\u0430 \u0431\u0443\u043c\u0430\u0436\u043d\u043e\u043c \u043d\u043e\u0441\u0438\u0442\u0435\u043b\u0435. \u041e\u043f\u044f\u0442\u044c \u0436\u0435 \u0441 \u0441\u043e\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u0435\u043c \u0432\u0441\u0435\u0445 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440.<\/p>\n<h3>\u041a\u0430\u043a \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435?<\/h3>\n<p>\u041f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0436\u0435\u0442 \u043b\u044e\u0431\u043e\u0439 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440 \u0432 \u0441\u0435\u0442\u0438. \u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u0434\u0438\u043e\u0434. \u0414\u0430\u043b\u0435\u0435 \u043e\u043d \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0443\u0436\u0435 \u043d\u0430 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0443\u0440. \u0412 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0434\u0438\u043e\u0434\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0451\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u0440\u0438\u0451\u043c\u0430 \u0430\u0434\u0440\u0435\u0441\u0430 \u0438 \u043f\u043e\u0440\u0442\u044b.<\/p>\n<p>\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 UDP, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0443 \u0431\u0435\u0437 \u043f\u043e\u0442\u0435\u0440\u044c. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0434\u043d\u043e \u0438 \u0442\u043e \u0436\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u043f\u043e\u0434\u0440\u044f\u0434 \u0441 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u043c\u0435\u0436\u0434\u0443 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044f\u043c\u0438. \u0422\u0430\u043a\u0436\u0435, \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u043d\u0435 \u0446\u0435\u043b\u0438\u043a\u043e\u043c, \u0430 \u0441 \u0440\u0430\u0437\u0431\u0438\u0432\u043a\u043e\u0439 \u043d\u0430 \u043f\u0430\u043a\u0435\u0442\u044b. \u041a\u0430\u0436\u0434\u044b\u0439 \u043f\u0430\u043a\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0444\u043e\u0440\u043c\u0438\u0442\u044c, \u0442\u0430\u043a \u0436\u0435 \u043a\u0430\u043a \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u043f\u0430\u043a\u0435\u0442\u0430\u0445, \u0447\u0442\u043e\u0431\u044b \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432. \u0411\u043b\u043e\u043a\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0445\u044d\u0448\u0430\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0446\u0435\u043b\u043e\u0441\u0442\u043d\u043e\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438.<\/p>\n<p>\u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u043d\u0430\u0434\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 5 \u0440\u0430\u0437) \u0441 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430\u043c\u0438 \u043c\u0435\u0436\u0434\u0443 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435\u0439 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0434\u043d\u0443 \u0441\u0435\u043a\u0443\u043d\u0434\u0443).<\/p>\n<h2>\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/h2>\n<p>\u0418\u0442\u0430\u043a, \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0445\u0435\u043b\u043f\u0435\u0440, \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0437\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0434\u0430\u043d\u043d\u044b\u0445. \u0414\u0430\u043b\u0435\u0435 \u0442\u0435\u0437\u0438\u0441\u043d\u043e&#8230;<\/p>\n<p>\u0414\u043b\u0438\u043d\u0430 \u043f\u0430\u043a\u0435\u0442\u0430<\/p>\n<pre><code class=\"php\">const SEND_BYTES_MAX = 1500;<\/code><\/pre>\n<p>\u0410\u0434\u0440\u0435\u0441 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438<\/p>\n<pre><code class=\"php\">public function __construct($host, $port)<\/code><\/pre>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0448\u0430\u0433\u043e\u0432<\/p>\n<pre><code class=\"php\">public function send($data) { $this->createSocket();  \/\/ \u043f\u043e\u0434\u043d\u044f\u0442\u044c \u0441\u043e\u043a\u0435\u0442 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0447\u0435\u0440\u0435\u0437 UDP $this->splitWithUnicode($data);  \/\/ \u0440\u0430\u0437\u0431\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u0431\u043b\u043e\u043a\u0438 $this->sendMetadata();  \/\/ \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 $this->sendSplits();  \/\/ \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0431\u043b\u043e\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 $this->sendEnding();  \/\/ \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 $this->closeSocket();  \/\/ \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u0441\u043e\u043a\u0435\u0442 }<\/code><\/pre>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u043e\u043a\u0435\u0442\u0430<\/p>\n<pre><code class=\"php\">protected function createSocket() { $this->socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); if ($this->socket === false) { $errorCode = socket_last_error(); $errorMessage = socket_strerror($errorCode); $this->logger->critical('\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u043a\u0435\u0442 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.', ['errorCode' => $errorCode, 'errorMessage' => $errorMessage]); throw new RuntimeException('\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u043a\u0435\u0442 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.'); } }<\/code><\/pre>\n<p>\u0420\u0430\u0437\u0431\u0438\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0431\u043b\u043e\u043a\u0438 \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438. \u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u043b\u0438\u043d\u0430 \u0431\u043b\u043e\u043a\u0430 \u0437\u0430\u0434\u0430\u0451\u0442\u0441\u044f \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u043e\u0439. \u041a\u0430\u0436\u0434\u044b\u0439 \u0431\u043b\u043e\u043a \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u0434\u043b\u0438\u043d\u044b \u0431\u0430\u0439\u0442. \u041a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430 \u043d\u0443\u0436\u043d\u0430 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0440\u0430\u0437\u0431\u0438\u0432\u043a\u0438 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438.<\/p>\n<p>\u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0444\u0443\u043d\u043a\u0446\u0438\u044f mb_str_split \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 PHP 7.4.<\/p>\n<pre><code class=\"php\">protected function splitWithUnicode($data) { $this->splits = []; $maxLength = self::SEND_BYTES_MAX \/ 2; $dataLength = mb_strlen($data, \"UTF-8\"); for ($i = 0; $i &lt; $dataLength; $i += $maxLength) { $this->splits[] = mb_substr($data, $i, $maxLength, \"UTF-8\"); } }<\/code><\/pre>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<pre><code class=\"php\">protected function sendMetadata() { $metadata = [ 'countSplits' => count($this->splits),  \/\/ \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0431\u043b\u043e\u043a\u043e\u0432 ]; if ($this->code) { $metadata['code'] = $this->code;  \/\/ \u043a\u043e\u0434 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 } if ($this->name) { $metadata['name'] = $this->name;  \/\/ \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0438\u043c\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430, \u0438\u043b\u0438 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u043b\u043e\u043a\u0430 } $this->sendDataWithHash(json_encode($metadata));  \/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c JSON-\u0441\u0442\u0440\u043e\u043a\u0443 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 }<\/code><\/pre>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u0445\u044d\u0448\u0435\u043c. 8 \u0431\u0430\u0439\u0442 \u0432\u043f\u0435\u0440\u0435\u0434\u0438 \u0431\u043b\u043e\u043a\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0445\u044d\u0448 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u043d\u0430\u0447\u0430\u043b\u043e \u0431\u043b\u043e\u043a\u0430.<\/p>\n<pre><code class=\"php\">protected function sendDataWithHash($data) { $hash = hash('crc32', $data); $hashAndData = $hash . $data; $this->sendData($hashAndData); }<\/code><\/pre>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<pre><code class=\"php\">protected function sendData($data) { $sent = socket_sendto($this->socket, $data, strlen($data), 0, $this->host, $this->port); if ($sent === false) { $errorCode = socket_last_error(); $errorMessage = socket_strerror($errorCode); $this->logger->warning('\u0414\u0430\u043d\u043d\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 \u0441\u043e\u043a\u0435\u0442 \u043d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u044b.', ['errorCode' => $errorCode, 'errorMessage' => $errorMessage]); } time_sleep_until(microtime(true) + .001);  \/\/ \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430 \u043c\u0435\u0436\u0434\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430\u043c\u0438 \u0431\u043b\u043e\u043a\u043e\u0432 \u043f\u043e \u0441\u0435\u0442\u0438. \u041f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f 1,5 \u043c\u0435\u0433\u0430\u0431\u0430\u0439\u0442\u0430 \u0437\u0430 \u043e\u0434\u043d\u0443 \u0441\u0435\u043a\u0443\u043d\u0434\u0443. }<\/code><\/pre>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0431\u043b\u043e\u043a\u043e\u0432<\/p>\n<pre><code class=\"php\">protected function sendSplits() { foreach ($this->splits as $split) { $this->sendDataWithHash($split); } }<\/code><\/pre>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0441\u0442\u0440\u043e\u043a\u0438 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f<\/p>\n<pre><code class=\"php\">protected function sendEnding() { $endingString = chr(0); $this->sendData($endingString); }<\/code><\/pre>\n<p>\u0417\u0430\u043a\u0440\u044b\u0442\u0438\u0435 \u0441\u043e\u043a\u0435\u0442\u0430<\/p>\n<pre><code class=\"php\">protected function closeSocket() { socket_close($this->socket); }<\/code><\/pre>\n<p>\u0412\u0435\u0441\u044c \u043a\u043b\u0430\u0441\u0441 \u043f\u043e\u0434 \u0441\u043f\u043e\u0439\u043b\u0435\u0440\u043e\u043c.<\/p>\n<details class=\"spoiler\">\n<summary>Hidden text<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"php\">&lt;?php  namespace Application\\Workers\\Udp;  use Application\\Logger\\AppLogger; use RuntimeException;  \/**  * \u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 UDP.  *\/ class UdpSender {     const SEND_BYTES_MAX = 1500;      \/** @var string *\/     protected $host;      \/** @var integer *\/     protected $port;      \/** @var AppLogger *\/     protected $logger;      \/** @var integer|string *\/     protected $code;      \/** @var string *\/     protected $name;      \/** @var resource *\/     protected $socket;      \/** @var array *\/     protected $splits;      \/**      * @param string $host      * @param integer $port      *\/     public function __construct($host, $port)     {         $this->host = $host;         $this->port = $port;         $this->logger = new AppLogger('Request');     }      \/**      * \u041f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u043a\u043e\u0434 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430.      *      * @param integer|string $code      * @return UdpSender      *\/     public function withCode($code)     {         $this->code = $code;         return $this;     }      \/**      * \u041f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430.      *      * @param string $name      * @return UdpSender      *\/     public function withName($name)     {         $this->name = $name;         return $this;     }      \/**      * \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435.      *      * @param string $data      * @return void      *\/     public function send($data)     {         $this->createSocket();         $this->splitWithUnicode($data);         $this->sendMetadata();         $this->sendSplits();         $this->sendEnding();         $this->closeSocket();     }      \/**      * \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u043a\u0435\u0442 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.      *      * @return void      *\/     protected function createSocket()     {         $this->socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);         if ($this->socket === false) {             $errorCode = socket_last_error();             $errorMessage = socket_strerror($errorCode);             $this->logger->critical('\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u043a\u0435\u0442 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.', ['errorCode' => $errorCode, 'errorMessage' => $errorMessage]);             throw new RuntimeException('\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u043a\u0435\u0442 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.');         }     }      \/**      * \u0420\u0430\u0437\u0431\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u043d\u0430 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0441 \u0443\u0447\u0451\u0442\u043e\u043c Unicode.      *      * @param string $data      * @return void      *\/     protected function splitWithUnicode($data)     {         $this->splits = [];         $maxLength = self::SEND_BYTES_MAX \/ 2;         $dataLength = mb_strlen($data, \"UTF-8\");         for ($i = 0; $i &lt; $dataLength; $i += $maxLength) {             $this->splits[] = mb_substr($data, $i, $maxLength, \"UTF-8\");         }     }      \/**      * \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435.      *      * @return void      *\/     protected function sendMetadata()     {         $metadata = [             'countSplits' => count($this->splits),         ];         if ($this->code) {             $metadata['code'] = $this->code;         }         if ($this->name) {             $metadata['name'] = $this->name;         }         $this->logger->debug('\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445.', ['metadata' => $metadata]);         $this->sendDataWithHash(json_encode($metadata));     }      \/**      * \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0441 \u0445\u044d\u0448\u0435\u043c.      *      * @param string $data      * @return void      *\/     protected function sendDataWithHash($data)     {         $hash = hash('crc32', $data);         $hashAndData = $hash . $data;         $this->sendData($hashAndData);     }      \/**      * \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435.      *      * @param string $data      * @return void      *\/     protected function sendData($data)     {         $sent = socket_sendto($this->socket, $data, strlen($data), 0, $this->host, $this->port);         if ($sent === false) {             $errorCode = socket_last_error();             $errorMessage = socket_strerror($errorCode);             $this->logger->warning('\u0414\u0430\u043d\u043d\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 \u0441\u043e\u043a\u0435\u0442 \u043d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u044b.', ['errorCode' => $errorCode, 'errorMessage' => $errorMessage]);         }         time_sleep_until(microtime(true) + .001);     }      \/**      * \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0447\u0430\u0441\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.      *      * @return void      *\/     protected function sendSplits()     {         $this->logger->debug('\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 \u0441\u043e\u043a\u0435\u0442.', ['countSplits' => count($this->splits)]);         foreach ($this->splits as $split) {             $this->sendDataWithHash($split);         }     }      \/**      * \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f.      *      * @return void      *\/     protected function sendEnding()     {         $endingString = chr(0);         $this->sendData($endingString);     }      \/**      * \u0417\u0430\u043a\u0440\u044b\u0442\u044c \u0441\u043e\u043a\u0435\u0442.      *      * @return void      *\/     protected function closeSocket()     {         socket_close($this->socket);     }  }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<h2>\u041f\u0440\u0438\u043d\u044f\u0442\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0443\u0440\u0430<\/h2>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441\u0435\u0440\u0432\u0438\u0441. \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043d\u0435 \u0432\u0445\u043e\u0434\u0438\u0442 \u0432 \u0434\u0430\u043d\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e. \u0415\u0441\u043b\u0438 \u043a\u043e\u0440\u043e\u0442\u043a\u043e, \u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u0434\u0435\u043c\u043e\u043d, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u041e\u0421. \u041e\u043d \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043d\u0430\u0448 PHP-\u0441\u043a\u0440\u0438\u043f\u0442, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0439 \u0437\u0430 \u043f\u0440\u0438\u0451\u043c \u0434\u0430\u043d\u043d\u044b\u0445. \u041f\u0440\u0438 \u043f\u0430\u0434\u0435\u043d\u0438\u0438 PHP-\u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0434\u0435\u043c\u043e\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0441\u0435\u0440\u0432\u0438\u0441.<br \/>\u0421\u043a\u0440\u0438\u043f\u0442 \u0446\u0438\u043a\u043b\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u043e\u0441\u043b\u0443\u0448\u0438\u0432\u0430\u0435\u0442 \u0441\u043e\u043a\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430<\/p>\n<pre><code class=\"php\">public function executeService() { $this->connectToSocket(); while (true) {  \/\/ \u0412\u0435\u0447\u043d\u044b\u0439 \u0446\u0438\u043a\u043b $this->receiveData();  \/\/ \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 $this->defineData();  \/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 } }<\/code><\/pre>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-353764","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/353764","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=353764"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/353764\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=353764"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=353764"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=353764"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}