如何将消息传递给websocket? [英] How to pass message to websocket?

查看:33
本文介绍了如何将消息传递给websocket?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 twig 模板,我正在尝试在 url 中发送具有相同标记的消息 从 http://url/{token1} 发送的含义消息只能由另一个具有相同标记的 url 接收令牌.

但我无法将任何消息从树枝传递到节点再到 symfony.

index.html.twig

<div><div class="form-group"><label for="name">名称:</label><输入类型=文本"id=名称">

<div class="form-group"><label for="message">Message:</label><输入类型=文本"id=消息">

<按钮类型=按钮"id=sendBtn"class=btn-primary">发送</按钮>

<script src="/bin/ws-broker.js"></script><脚本>const socket = new WebSocket("ws://localhost:8080");document.getElementById("sendBtn").addEventListener("click", function() {常量消息 = {名称:document.getElementById("name").value,消息:document.getElementById("message").value};socket.send(JSON.stringify(message));});

/bin/ws-broker.js

const WebSocket = require('ws');const qs = require('querystring');const wss = new WebSocket.Server({ port: 8080 });const http = require('http');wss.on('connection', 函数连接(ws, req){console.log('从 IP 接收到的连接:' + req.socket.remoteAddress);ws.on('message', 函数传入(message) {if ('' === 消息) {//空消息返回;}尝试 {//将消息处理为JSON对象消息 = JSON.parse(message);}赶上(e){//无法将消息解析为 JSON返回;}});});console.log('监听 8080 端口');

控制器

/*** @Route("/{token}", name="home")*/公共函数索引():响应{return $this->render('home/index.html.twig', ['控制器名称' =>'家庭控制器',]);}

解决方案

围绕 NodeJS WebSocket 代理服务和浏览器 WebSocket 客户端似乎存在一些混淆.

为了澄清,WebSocket 代理在后端作为服务器与 Apache 一起运行,以便侦听从浏览器 WebSocket 客户端发送的消息.与 Apache 侦听来自浏览器客户端的 HTTP 请求的方式相同.

WebSocket 代理服务器收到一条消息,然后将数据作为 HTTP 请求转发,以便 Symfony 可以处理请求并将代理传回 WebSocket 客户端的响应发回.

该过程与 Ratchet 的侦听方式相同,但没有使用 php bin/console app:command 在永久运行状态下加载 Symfony 和 Doctrine 的开销.除了已经在 Symfony 环境中的情况之外,bin/ws-broker.js 创建了一个 HTTP 请求以发送到 Symfony.

bin/ws-broker.js 流程分解是这样的.

浏览器 HTTP 请求 ->/path/to/index ->Symfony AppController::index() ->返回响应(Twig::render('index.html.twig')) ->WebSocket 客户端 - socket.send(message) ->[node bin/ws-broker.js WebSocket Server - ws.on('message')] ->[节点 bin/ws-broker.js http.request()] ->/path/to/score-handler ->Symfony AppController::scoreHandler() ->返回 JsonResponse(data) ->[node bin/ws-broker.js WebSocket Server - ws.send(response) to WebSocket Client] ->WebSocket 客户端 - socket.onmessage()

bin/console app:command Ratchet 进程分解是这样的.

浏览器 HTTP 请求 ->/path/to/index ->Symfony AppController::index() ->返回响应(Twig::render('index.html.twig')) ->WebSocket 客户端 - socket.send(message) ->[php bin/console app:command - Ratchet\MessageComponentInterface::onMessage()] ->[php bin/console app:command - $client->send(response) to WebSocket Client] ->WebSocket 客户端 - socket.onmessage()


将 Symfony HTTP 请求和响应处理程序添加到 NodeJS WebSocket 侦听器服务

//bin/ws-broker.jsconst WebSocket = require('ws');const qs = require('querystring');const http = require('http');const wss = new WebSocket.Server({ port: 8080 });wss.on('connection', 函数连接(ws, req) {console.log('从 IP 接收到的连接:' + req.socket.remoteAddress);ws.on('message', 函数传入(message) {if ('' === 消息) {//空消息返回;}尝试 {//将消息处理为JSON对象消息 = JSON.parse(message);}赶上(e){//无法将消息解析为 JSON返回;}//将WS消息转换为Symfony请求对象的查询字符串让 postData = qs.stringify({名称":message.name,消息":message.message});让 http_options = {主机:'本地主机',路径:'/' + message.token,端口:8000,方法:'POST',标题:{'内容类型':'应用程序/x-www-form-urlencoded','内容长度':postData.length}};//使用 HTTP 请求将消息转发到 Symfony让 req = http.request(http_options, function(res) {res.setEncoding('utf8');//处理Symfony响应数据让数据 = '';res.on('data', (chunk) => {数据 += 块});//将 Symfony 响应发送回 WebSocket 客户端res.on('end', function() {ws.send(数据);});});//将请求的消息发送到Symfonyreq.write(postData);请求结束();});});console.log('监听 8080 端口');

运行 WebSocket 代理服务器

node bin/ws-broker.js &

添加一个路由来处理 Broker 请求并将响应发送回 Broker.将令牌添加到 home/index.html.twig 上下文中.

class AppController extends AbstractController{/*** @Route("/{token}", name="score_handler", requirements={ "token":"\w+"; } methods={ "POST" })*/公共函数 scoreHandler(string $token): JsonResponse{//由bin/ws-broker.js调用//在这里做事...返回 $this->json(['数据' =>'收到消息!']);}/*** @Route("/{token}", name="home", requirements={ "token":"\w+" } methods={ "GET" })*/公共函数索引(字符串 $token):响应{//由Apache/浏览器调用return $this->render('home/index.html.twig', ['控制器名称' =>'家庭控制器','令牌' =>$令牌]);}}

从前端删除 bin/ws-broker.js,将令牌发送到 Broker 并添加响应处理程序

<div id="chat"></div><div><div class="form-group"><label for="name">名称:</label><输入类型=文本"id=名称">

<div class="form-group"><label for="message">Message:</label><输入类型=文本"id=消息">

<按钮类型=按钮"id=sendBtn"class=btn-primary">发送</按钮>

<script type="text/javascript">const socket = new WebSocket("ws://localhost:8080");socket.onmessage = 函数(evt){window.console.log(evt.data);//处理WebSocket服务器响应...};document.getElementById("sendBtn").addEventListener("click", function() {常量消息 = {名称:document.getElementById("name").value,消息:document.getElementById("message").value,令牌:{{令牌}}"//<------ 发送令牌到 WebSocket 服务器};socket.send(JSON.stringify(message));});

I have a twig template and I am trying to send message having same token in url Meaning message send from http://url/{token1} from should only be recived by another url with same token.

But I am not being able to pass any message from twig to node to symfony.

index.html.twig

<div id="chat">

</div>
<div>
    <div class="form-group">
        <label for="name">Name:</label> <input type="text" id="name">
    </div>
    <div class="form-group">
        <label for="message">Message:</label> <input type="text" id="message">
    </div>
    <button type="button" id="sendBtn" class="btn-primary">Send</button>
</div>

<script src="/bin/ws-broker.js"></script>
<script>
    const socket = new WebSocket("ws://localhost:8080");
    document.getElementById("sendBtn").addEventListener("click", function() {
        const message = {
            name: document.getElementById("name").value,
            message: document.getElementById("message").value
        };
        socket.send(JSON.stringify(message));
    });
</script>

/bin/ws-broker.js

const WebSocket = require('ws');
const qs = require('querystring');
const wss = new WebSocket.Server({ port: 8080 });
const http = require('http');

    wss.on('connection', function connection(ws, req)
    {
        console.log('Connection Received from IP: ' + req.socket.remoteAddress);
        ws.on('message', function incoming(message) {
            if ('' === message) {
                //empty message
                return;
            }
            try {
                //process message as JSON object
                message = JSON.parse(message);
            } catch (e) {
                //failed parsing the message as JSON
                return;
            }
    
        });
    });
    
    console.log('Listening on port 8080');

Controller

    /**
     * @Route("/{token}", name="home")
     */
    public function index(): Response
    {
        return $this->render('home/index.html.twig', [
            'controller_name' => 'HomeController',
        ]);
    }

解决方案

There appears to be some confusion surrounding the NodeJS WebSocket broker service and the Browser WebSocket client.

For clarification, the WebSocket broker runs on the backend as a server alongside Apache, in order to listen for messages being sent from browser WebSocket clients. In the same way that Apache listens for HTTP Requests from browser clients.

The WebSocket broker server receives a message then forwards the data as an HTTP Request so that Symfony can handle the request and send back a response that the broker passes back to the WebSocket client.

The process is identical to how Ratchet listens but without the overhead of Symfony and Doctrine being loaded in a perpetually running state by using php bin/console app:command. With the exception that instead of being in the Symfony environment already, bin/ws-broker.js creates an HTTP request to send to Symfony.

The bin/ws-broker.js process breakdown goes like this.

Browser HTTP Request -> /path/to/index -> 
  Symfony AppController::index() -> 
  return Response(Twig::render('index.html.twig')) -> 
    WebSocket Client - socket.send(message) -> 
      [node bin/ws-broker.js WebSocket Server - ws.on('message')] ->
      [node bin/ws-broker.js http.request()] -> /path/to/score-handler -> 
        Symfony AppController::scoreHandler() -> 
        return JsonResponse(data) ->  
      [node bin/ws-broker.js WebSocket Server - ws.send(response) to WebSocket Client] ->
    WebSocket Client - socket.onmessage()

The bin/console app:command Ratchet process breakdown goes like this.

Browser HTTP Request -> /path/to/index -> 
  Symfony AppController::index() -> 
  return Response(Twig::render('index.html.twig')) -> 
    WebSocket Client - socket.send(message) -> 
      [php bin/console app:command - Ratchet\MessageComponentInterface::onMessage()] ->
      [php bin/console app:command - $client->send(response) to WebSocket Client] ->
    WebSocket Client - socket.onmessage()


Add the Symfony HTTP Request and Response handler to the NodeJS WebSocket Listener Service

// bin/ws-broker.js

const WebSocket = require('ws');
const qs = require('querystring');
const http = require('http');
const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', function connection(ws, req) {
    console.log('Connection Received from IP: ' + req.socket.remoteAddress);
    ws.on('message', function incoming(message) {
        if ('' === message) {
            //empty message
            return;
        }

        try {
            //process message as JSON object
            message = JSON.parse(message);
        } catch (e) {
            //failed parsing the message as JSON
            return;
        }

        //convert the WS message to a query string for the Symfony Request object
        let postData = qs.stringify({
            "name": message.name, 
            "message": message.message
        });
        let http_options = {
            host: 'localhost',
            path: '/' + message.token,
            port: 8000,
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
                'Content-Length': postData.length
            }
        };

        //forward the message to Symfony using an HTTP Request
        let req = http.request(http_options, function(res) {
            res.setEncoding('utf8');
            //process the Symfony response data
            let data = '';
            res.on('data', (chunk) => {
                data += chunk
            });

            //send the Symfony Response back to the WebSocket client
            res.on('end', function() {
                ws.send(data);
            });
        });

        //send the requested message to Symfony
        req.write(postData);
        req.end();
    });
});

console.log('Listening on port 8080');

Run the WebSocket Broker Server

node bin/ws-broker.js &

Add a route to handle the Broker Request and send a Response back to the Broker. Add the token to the home/index.html.twig context.

class AppController extends AbstractController
{
    /**
     * @Route("/{token}", name="score_handler", requirements={ "token":"\w+" } methods={ "POST" })
     */
    public function scoreHandler(string $token): JsonResponse
    {
        //called by bin/ws-broker.js

        //do things here...

        return $this->json([
            'data' => 'Message Received!'
        ]);
    }

    /**
     * @Route("/{token}", name="home", requirements={ "token":"\w+" } methods={ "GET" })
     */
    public function index(string $token): Response
    {
        //called by Apache/Browser

        return $this->render('home/index.html.twig', [
            'controller_name' => 'HomeController',
            'token' => $token
        ]);
    }
}

Remove the bin/ws-broker.js from the frontend, send the token to the Broker and add a response handler

<!-- home/index.html.twig -->

<div id="chat"></div>
<div>
    <div class="form-group">
        <label for="name">Name:</label> <input type="text" id="name">
    </div>
    <div class="form-group">
        <label for="message">Message:</label> <input type="text" id="message">
    </div>
    <button type="button" id="sendBtn" class="btn-primary">Send</button>
</div>

<script type="text/javascript">
    const socket = new WebSocket("ws://localhost:8080");
    socket.onmessage = function(evt) {
        window.console.log(evt.data);
        //handle WebSocket Server Response...
    };
    document.getElementById("sendBtn").addEventListener("click", function() {
        const message = {
            name: document.getElementById("name").value,
            message: document.getElementById("message").value,
            token: "{{ token }}" //<------ SEND TOKEN to WebSocket Server
        };
        socket.send(JSON.stringify(message));
    });
</script>

这篇关于如何将消息传递给websocket?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
PHP最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆