Архив рубрики: WEB

WebSocket Ratchet сервер с одновременной прослушкой двух IP

Задача: поднять WebSocket сервер, одновременно слущающий и wss (для браузеров) и ws (для скриптов на PHP на том-же сервере).

Почему такой велосипед? Ну просто вот ну никак не удалось подобрать WebSocket клиент на PHP нормально работающий с WSS (SSL).

Решение:

$myClassMessage=new MessageService($UsersApi);

$loop = React\EventLoop\Factory::create();
$webSock = new React\Socket\Server('0.0.0.0:35500', $loop);
$webSock = new React\Socket\SecureServer($webSock, $loop, [
    'local_cert'        => 'епкуеп.crt', // path to your cert
    'local_pk'          => 'кепуке.key', // path to your server private key
    'allow_self_signed' => TRUE, // Allow self signed certs (should be false in production)
    'verify_peer' => FALSE
]);

$webServer = new Ratchet\Server\IoServer(
    new Ratchet\Http\HttpServer(
        new Ratchet\WebSocket\WsServer(
            $myClassMessage
        )
    ),
    $webSock,
    $loop        
);
$webSock2 = new React\Socket\Server('127.0.0.1:35501', $loop);

$webServer = new Ratchet\Server\IoServer(
    new Ratchet\Http\HttpServer(
        new Ratchet\WebSocket\WsServer(
            $myClassMessage
        )
    ),
    $webSock2,
    $loop        
);
$loop->run();

websocket сервер ratchet c SSL

Почемуто большинство примеров создания websocket сервера с использованием ratchet приведены без использования SSL.  И у всех как я почитаю пляски с буном потом с проксированием через apache или ngnix. Но ведь он умеет и без этого!

Вот примерно как это оформляется:

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use React\EventLoop\Factory;
use React\Socket\SecureServer; 

$loop = React\EventLoop\Factory::create();
$webSock = new React\Socket\Server('0.0.0.0:33423', $loop);
$webSock = new React\Socket\SecureServer($webSock, $loop, [
    'local_cert'        => 'sssss.crt', 
    'local_pk'          => 'sssss.key', 
    'allow_self_signed' => TRUE, 
    'verify_peer' => FALSE
]);

$webServer = new Ratchet\Server\IoServer(
    new Ratchet\Http\HttpServer(
        new Ratchet\WebSocket\WsServer(
            new MessageService($UsersApi)
        )
    ),
    $webSock,
    $loop        
);

$webServer->run();

А вот пример класса MessageService:

class MessageService implements MessageComponentInterface {
    protected $clients;
    public $cnt=0; 
    public $uapi="";
    public function __construct($uu) {
        $this->uapi=$uu;
        $this->clients = array();        
        echo "- запустили, ждем соединения..\n";
    }

    public function onOpen(ConnectionInterface $conn) {                
            $user["user"]="";
            $user["conn"]=$conn;
            $this->clients[]=$user;
            $this->cnt++;            
            echo "--с нами ".count($this->clients)."\n";
            echo "---спрашиваю who_are_you?\n";
            $conn->send(json_encode(array("command"=>"who_are_you")));
    }

    public function onMessage(ConnectionInterface $from, $msg) {
        echo "-- пришло сообщение: $msg \n";        
        $msg= json_decode($msg);
        //var_dump($msg);
        if (isset($msg->command)):
            switch ($msg->command) {
               case "who_am_i":
               // обхожу все соединения, и добавляю параметр - пришедший id пользователя
                    foreach ($this->clients as &$client) {
                        if ($from == $client["conn"]) {
                            $client["user"]=$msg->user;
                        };
                    };
               break;
               default:break;
            }
        endif;

    }

    public function onClose(ConnectionInterface $conn) { 
        $user="";
        foreach ($this->clients as $key=>$client) {          
          if ($client["conn"]==$conn):
              echo "-- ушел $key(".$client["user"].")\n";              
              $user=$client["user"];
              unset($this->clients[$key]);              
          endif;
        };
        echo "-- осталось соединений ".count($this->clients)."\n";
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        $conn->close();
    }
}

Яндекс карты: отображение очень большого количества обьектов на карте

Задача: отобразить на карте  ОЧЕНЬ большого количества обьектов на карте:

Решение: для отображения используем ObjectManager с включенной кластеризаций, кроме того, обекты загружаем через JSON с типом «Feature» — т.е. метки загружаются ни как обьекты, а как «теневой массив», который не умеет отображать контент,хинты и имеет еще ряд ограничений. Этот момент мы обходим следующим образом: при наведении курсора мышки на  метку, мы переносим её в «обьекты».

javascript:

    var myMap;    
    latitude=55.76;
    longitude=37.64;
    navigator.geolocation.getCurrentPosition(
    function(location) {
      latitude=location.coords.latitude;
      longitude=location.coords.longitude;
      accuracy=location.coords.accuracy;
      ymaps.ready(init);
    },
    function(error){
        ymaps.ready(init);        
    }
    );    


function init () {
    console.log("-инициируем карту в "+latitude+" и "+longitude);
    myMap = new ymaps.Map('map', {
        center: [latitude, longitude], 
        controls: ['trafficControl','zoomControl','routeButtonControl','routeEditor'],
        zoom: 15
    }, {
        searchControlProvider: 'yandex#search'
    });    
    if (isMobile.any()) {
        console.log("-открыто на мобильнике - отключаем мультитач");
        //myMap.behaviors.disable('drag');
        myMap.behaviors.disable('multiTouch');
    }
    LoadEVCByCar(<?=$Users->defaultcar?>);
}    
function LoadEVCByCar(carcode){
    //очищаем холст
    myMap.geoObjects.removeAll();
    NormalCollection = new ymaps.GeoObjectCollection();
    //теневые не полноценные обьекты загружаем скопом
    objectManager = new ymaps.ObjectManager({clusterize: true}); 
    myMap.geoObjects.add(objectManager);        
    $.post("csdcsdcs", {  
        carcode:carcode,
        latitude:latitude,
        longitude:longitude
    }).done(function(data) {
        jsond=JSON.parse(data);
        objectManager.add(jsond);    
    });
    // по событию "попадание мышкой" теневой обьект удаляем и создаем "настоящий" полноценный, с которым далее и работаем..
    objectManager.objects.events.add(['mouseenter', 'mouseleave'], Shadow2Normal);
  
};
function Shadow2Normal (e) {
    aa=e;
    console.log(e);
    if (e.get('type') == 'mouseenter') {        
        objectIdcur = e.get('objectId');
        newob=objectManager.objects.getById(objectIdcur);
        myMap.geoObjects.remove([objectIdcur]);
        objectManager.remove([objectIdcur]);
                
        newob.options["draggable"]=false;
        newob.options["id"]=newob.id;
        NormalObject = new ymaps.GeoObject(
                {
                    id:   newob.id,
                    geometry :   newob.geometry,
                    properties:  newob.properties
                },
                    newob.options
                );
        
        NormalCollection.add(NormalObject); //добавляем в коллекцию    
        myMap.geoObjects.add(NormalCollection); // добавляем на холст                  
        
    };
}

PHP:

<?php
    $JsonEVCS=array();
    $JsonEVCS["type"]="FeatureCollection";
    
    $longitude= _POST("longitude");
    $latitude= _POST("latitude");
    $carcode= _POST("carcode");
    for ($i = 1; $i <= 10000; $i++) {
            $evcs_info=array();
            $evcs_info["type"]="Feature";
            $evcs_info["id"]=$i;        
            $evcs_info["geometry"]["type"]="Point";
            $m1=rand(0,1);if ($m1==0){$m1=-1;};
            $m2=rand(0,1);if ($m2==0){$m2=-1;};
            $evcs_info["geometry"]["coordinates"]=array($latitude+$m1*rand(1,200)/100,$longitude+$m2*rand(1,200)/100);                                
            $evcs_info["properties"]["balloonContent"]="html код";
            $evcs_info["properties"]["hintContent"]="Подсказка";
            $evcs_info["properties"]["data"]["ip"]="32у23";  
            $evcs_info["options"]["preset"]="islands#redDotIcon";
            $evcs_info["properties"]["iconContent"]="Имя";
            $evcs_info["options"]["draggable"]=false;
            $evcs_info["options"]["hideIconOnBalloonOpen"]=false;
            $JsonEVCS["features"][]=$evcs_info;
    };
  echo json_encode($JsonEVCS);

Убираем из URL адресной строки на странице сайта лишнее

Задача: убрать из адресной строки страницы сайта открытой по ссылке из поисковика Яндекса, «лишнюю» информацию, которая идет «прицепом» от яндекса.

Решение:

<script>    
function UrlBrowserYandexCuter(){
   path=document.location.pathname.split("yclid");
   path=path[0];
   search=document.location.search.split("yclid");;
   search=search[0];
   hash=document.location.hash.split("yclid");;
   hash=hash[0];
   url=path+search+hash;
   if (url.slice(-1)=="?"){
    url=url.substring(0, url.length - 1);   
   };
   history.replaceState(null,null, url);
};
UrlBrowserYandexCuter();
</script>

Overloading of string functions using mbstring.func_overload is not supported by phpseclib

Чаще всего эта ошибка появляется, когда на сервере установлен битрикс, а в php.ini выставлено mbstring.func_overload=2 (иначе Битрикс в UTF работать не захочет).

Решение:

В .htpaccess добавляем 

php_value mbstring.func_overload 0
php_value mbstring.internal_encoding UTF-8