如何将消息传递到websocket



我有一个小树枝模板,我正在尝试发送url中具有相同令牌的消息。这意味着从http://url/{token1}发送的消息应该只能由具有相同标记的另一个url接收。

但我无法将任何消息从树枝传递到节点,再传递到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');

控制器

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

围绕NodeJS WebSocket代理服务和Browser WebSocket客户端似乎存在一些混淆。

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

WebSocket代理服务器接收一条消息,然后将数据作为HTTP请求转发,这样Symfony就可以处理该请求并发回一个响应,代理将该响应传递回WebSocket客户端。

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

bin/ws-broker.js进程分解如下。

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()

bin/console应用程序:命令棘轮进程分解如下。

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 - RatchetMessageComponentInterface::onMessage()] ->
[php bin/console app:command - $client->send(response) to WebSocket Client] ->
WebSocket Client - socket.onmessage()

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

// 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');

运行WebSocket Broker服务器

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" })
*/
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
]);
}
}

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

<!-- 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>

最新更新