2012-02-23 22 views
6

So che questa domanda è un po 'imbarazzante, ma il problema deriva da Samsung TV 2010/2011 SmartTV (e lettore blu ray, ovviamente l'emulatore 2012 funziona bene). Ho portato i semplici esempi di chat provenienti dalla sorgente e dal pacchetto all'app SmartTV. Entrambe rientrano nel polling JSONP, ma dall'app SmartTV possono essere emesse/inviate al server una sola volta. Ricevere il messaggio dal server potrebbe essere più volte senza alcun problema. Dopo aver cercato la risposta nel forum Samsung D (ovviamente nulla lì), penso che il modo più veloce per aggirare questo problema è quello di distribuire un server Express, prendendo i dati del post e JSON.parse, quindi emettere Socket.io/Sockjs internamente all'interno del server stesso.Come utilizzare Express post request per emettere Socket.io o Sockjs?

Qualcuno potrebbe mostrarmi un codice di esempio facile in modo da poter iniziare da lì? Molte grazie.

ho subito rendere il codice, ma sembra che non funziona:

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> 

'il mio altro evento' non sembra ricevere qualsiasi cosa

+0

Ho trovato la soluzione. il "mio altro evento" a un'altra funzione e lasciare che sia post ed emetti chiamarlo.Ma questo problema risolva, ho bisogno di gestire il socket che si connette su altra linea. – user1045217

risposta

12

AGGIORNAMENTO: Ho aggiornato l'esempio per renderlo più completo. Non ho avuto un app.listen prima, e qui è anche uno script lato client che dimostra che, in effetti, funziona bene:

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

e il server, ora con una direttiva 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); 

Uso:

node app.js 

Passare a http://localhost:3000/ e fare clic sul pulsante. Controlla la tua console per l'output.

+0

grazie, ma sembra non funzionare. – user1045217

+0

Ho aggiornato il esempio, è a prova di proiettile. –

+0

Linus, quello che ho cercato di fare è di emettere qualcosa scritto nel server (auto-emit, post esplicito su socket.io emit). Il server spinge al meccanismo client che funziona piuttosto bene su Samsung SmartTV (vorrei Dite StupidTV personalmente) Se inserisco io.socket.on ("foo", function (message) {// emette un altro al client o semplicemente accede console} dopo app.listen (3000), non farà nulla. – user1045217

2

Sulla base SockJS express example server.js potrebbe apparire come:

 
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({}); 
}); 

Per testare il browser aperto a localhost: 9999 ed eseguire:

curl localhost:9999/send -X POST 
+0

Apprezzo il tuo lavoro. Comunque l'esempio non sembra funzionare dalla mia parte. 0. Non ho visto "POST ricevuto" visualizzato sulla console. 1. Ho creato un semplice client html (index.html) per fare solo una richiesta. Inizialmente pensavo che sarebbe stato montato su localhost: 9999/echo/ma è su localhost: 9999 /. 2. La stessa cosa accade sul post lanciato da html. – user1045217

1

Non so se questo aiuterebbe, ma puoi creare un'astrazione di emulazione sul client basata sul tuo browser e quindi creare una funzione get separata sul server che gestirà la richiesta allo stesso modo del socket.on callback. Per sapere dove inviare le informazioni, suggerisco di utilizzare una chiave che è possibile memorizzare in una tabella hash nel server e nella memoria locale sul client.

Per il cliente:

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

Per il 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); 
}); 

Un altro modo per farlo sarà quello di passare a Sockjs e utilizzare il loro patch.

Se qualcuno ha una soluzione migliore per Socket.IO sarà apprezzato, perché sono già in profondità nel progetto ed è troppo tardi per cambiare Socket.IO per Sockjs, e questa soluzione non è di mio gradimento :(.