如何使用Express post请求发出Socket.io或Sockjs?

时间:2022-03-20 04:12:01

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

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

“我的其他事件”似乎没有收到任何东西。

3 个解决方案

#1


12  

UPDATE: I updated the example for you to make it more complete. I didn't have an app.listen before, 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.listen directive:

和服务器,现在有一个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 /并单击按钮。检查控制台输出。

#2


2  

Based on SockJS express example server.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

#3


0  

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并使用他们的补丁。

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为时已晚,而且这个解决方案不符合我的喜好:(。

#1


12  

UPDATE: I updated the example for you to make it more complete. I didn't have an app.listen before, 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.listen directive:

和服务器,现在有一个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 /并单击按钮。检查控制台输出。

#2


2  

Based on SockJS express example server.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

#3


0  

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并使用他们的补丁。

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为时已晚,而且这个解决方案不符合我的喜好:(。