node.js 如何使用 Express post 请求发出 Socket.io 或 Sockjs?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9411793/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use Express post request to emit Socket.io or Sockjs?
提问by user1045217
I know this question is kind of awkward, but the problem comes from Samsung TV 2010 / 2011 SmartTV (and blue ray player; of course 2012 emulator working fine). I ported the simple chatting examples come from the source and package to SmartTV app. Both of them fall back to JSONP polling, but from SmartTV app only could emit / push to server once. Receiving the message from server could be multiple times without any problem. After looking for the answer in Samsung D forum (of course nothing there), I think the fastest way to work around this issue is to deploy an Express server, taking the post data and JSON.parse, then emit Socket.io / Sockjs internally inside the server itself.
我知道这个问题有点尴尬,但问题来自三星电视 2010 / 2011 SmartTV(和蓝光播放器;当然 2012 模拟器工作正常)。我将源代码和包中的简单聊天示例移植到 SmartTV 应用程序中。它们都回退到 JSONP 轮询,但从 SmartTV 应用程序只能发送/推送到服务器一次。从服务器接收消息可能多次没有任何问题。在三星 D 论坛上寻找答案后(当然没有),我认为解决这个问题的最快方法是部署一个 Express 服务器,获取 post 数据和 JSON.parse,然后在内部发出 Socket.io / Sockjs在服务器本身内部。
Could anybody show me an easy sample code so I could start from there? Thanks a lot.
有人可以给我看一个简单的示例代码,这样我就可以从那里开始吗?非常感谢。
I quickly make code, but seems it doesn't work:
我很快编写了代码,但似乎不起作用:
lib/server.js
库/server.js
var express = require('express')
, app = express.createServer()
, io = require('socket.io').listen(app);
app.listen(80);
app.use(express.bodyParser());
app.get('/', function (req, res) {
res.sendfile('/var/www/mpgs_lite_v3/index.html');
});
app.post('/', function(req, res){
console.log(req.body);
io.sockets.emit('my other event', req.body);
res.redirect('back');
});
io.sockets.on('connection', function (socket) {
//socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
index.html
索引.html
<html>
<head>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
</head>
<body>
<form method="post" action="/">
<input type="hidden" name="_method" value="put" />
<input type="text" name="user[name]" />
<input type="text" name="user[email]" />
<input type="submit" value="Submit" />
</form>
</body>
</html>
'my other event' seems not receive anything.
“我的其他活动”似乎没有收到任何消息。
回答by Linus Gustav Larsson Thiel
UPDATE:I updated the example for you to make it more complete. I didn't have an app.listenbefore, and here is also a client side script which shows that it, indeed, works fine:
更新:我为您更新了示例以使其更完整。我以前没有app.listen,这里还有一个客户端脚本,它表明它确实可以正常工作:
<!doctype html>
<html>
<head>
<script src="//www.google.com/jsapi"></script>
<script src="/socket.io/socket.io.js"></script>
<script>google.load("jquery", "1.7.1")</script>
<script>
var socket = io.connect("localhost", {port: 3000});
socket.on("foo", function(message) { console.log("foo: ", message) });
$(function() {
$("button").click(function() {
$.post("/foo", { message: $("input").val() });
});
});
</script>
</head>
<body>
<input type=text>A message</input>
<button>Click me!</button>
</body>
</html>
And the server, now with an app.listendirective:
和服务器,现在有一个app.listen指令:
var express = require("express"),
app = express.createServer(),
io = require("socket.io").listen(app)
index = require("fs").readFileSync(__dirname + "/index.html", "utf8");
app.use(express.bodyParser());
app.get("/", function(req, res, next) {
res.send(index);
});
app.post("/foo", function(req, res, next) {
io.sockets.emit("foo", req.body);
res.send({});
});
app.listen(3000);
Usage:
用法:
node app.js
Navigate to http://localhost:3000/and click the button. Check your console for output.
导航到http://localhost:3000/并单击按钮。检查您的控制台是否有输出。
回答by Marek
Based on SockJS express exampleserver.js could look like:
基于SockJS express 示例server.js 可能如下所示:
var express = require('express');
var sockjs = require('sockjs');
// 1. Echo sockjs server
var sockjs_opts = {sockjs_url: "http://cdn.sockjs.org/sockjs-0.2.min.js"};
var sockjs_echo = sockjs.createServer(sockjs_opts);
connections = {};
sockjs_echo.on('connection', function(conn) {
console.log(conn.id);
connections[conn.id] = conn
conn.on('close', function() {
delete connections[conn.id];
});
// Echo.
conn.on('data', function(message) {
conn.write(message);
});
});
// 2. Express server
var app = express.createServer();
sockjs_echo.installHandlers(app, {prefix:'/echo'});
console.log(' [*] Listening on 0.0.0.0:9999' );
app.listen(9999, '0.0.0.0');
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
app.post("/send", function(req, res, next) {
for(var id in connections) {
connections[id].write('received POST');
}
res.send({});
});
To test open browser at localhost:9999 and run:
要在 localhost:9999 上测试打开的浏览器并运行:
curl localhost:9999/send -X POST
回答by virk
just remove this comment //socket.emit('news', { hello: 'world' }); to socket.emit('news', { hello: 'world' });
只需删除此评论 //socket.emit('news', { hello: 'world' }); 到 socket.emit('news', { hello: 'world' });
it will work because its emiting data through news and you are listening using my other event instead of 'news' or you can do just listen using 'my other event'
它会起作用,因为它通过新闻发出数据,并且您正在使用我的其他事件而不是“新闻”进行收听,或者您可以只使用“我的其他事件”进行收听
回答by DaniOcean
I don't know if this would help, but you can make an emit abstraction on the client based on your browser and then make a separate get function on the server that will handle the request the same way as the socket.on callback. In order to know where to send the information I suggest you use some key that you can store in a hash table in the server and local storage on the client.
我不知道这是否会有所帮助,但是您可以根据浏览器在客户端上创建一个发射抽象,然后在服务器上创建一个单独的 get 函数,该函数将以与 socket.on 回调相同的方式处理请求。为了知道将信息发送到哪里,我建议您使用一些可以存储在服务器哈希表和客户端本地存储中的密钥。
For the client:
对于客户:
var emit = function(event, options) {
if ("WebSocket" in window) {
socket.emit(event, options);
console.log("emited via WebSocket");
} else {
$.post("http://localhost/emit/" + event, options);
console.log("emited via AJAX");
}
}
emit("echo", {
key: localStorage.getItem("key"),
data: {
hello: "world"
}
});
socket.on("response", function(data) {
console.log(data.hello); //will print "world"
});
For the server:
对于服务器:
var sockets = {};
var echo_handler = function(a) {
var socket = sockets[a.key];
var data = a.data;
socket.emit("response", data);
}
app.post("/emit/:event", function(req, res) {
var event = req.params.event;
switch (event) {
case "echo":
var a = {
key: req.param("key"),
data: req.param("data")
}
echo_handler(a);
break;
}
});
io.sockets.on("connection", function(socket) {
socket.on("connect", function(data) {
sockets[data.key] = socket;
});
socket.on("echo", echo_handler);
});
Another way to do this will be to switch to Sockjs and use their patch.
另一种方法是切换到 Sockjs 并使用他们的patch。
If someone have better solution for Socket.IO it will be appreciated, because I'm already deep into the project and it's too late to switch Socket.IO for Sockjs, and this solution is not to my liking :( .
如果有人对 Socket.IO 有更好的解决方案,我将不胜感激,因为我已经深入到该项目中,现在为 Sockjs 切换 Socket.IO 为时已晚,而且我不喜欢这个解决方案:(。

