NodeJS:客户端通过服务器到客户端

时间:2015-12-13 14:04:09

标签: node.js sockets server

我通过服务器将数据从客户端发送到客户端有一点问题(避免在客户端上侦听端口)。

我有这样的服务器:

var net = require("net");
var server = net.createServer(function(socket) {
    socket.on("data", function(data) {

    });
});
server.listen(port);

现在我想通过服务器将数据从一个客户端重定向到另一个客户端。但我不知道如何做到这一点,因为我不知道如何从另一个连接中解决连接问题。

有谁知道,我怎么能这样做?

2 个答案:

答案 0 :(得分:0)

您可以将所有客户端保存在一个简单的数组中,并将其发送到每个客户端,而无需客户端的套接字ID。所以每个客户只会获得所有其他客户。然后你可以通过客户端ID来解决它:

var net = require("net");
var clients = {};
var server = net.createServer(function(socket) {

    socket.on("connect", function ()
    {
        // Get the socket id of the connected client
        var socketId = null;

        // Get the client socket
        var clientSocket = null;

        clients[socketId] = clientSocket;
    });

    // Socket is the client
    socket.on("data", function(data) {

        var d = JSON.parse(data);

        if (d.client)
        {
            if (!clients[d.client.id])
            {
                // Client doesn't exists
                return;
            }

            // Send messages to the client with the saved socket
            clients[d.client.id].send(d.data);
        }

    });

    socket.on("end", function ()
    {
        // Get the socket id of the disconnected client
        var socketId = null;

        delete clients[socketId];
    });
});
server.listen(port);

我知道与socket.io合作,我强烈建议你也可以使用它。

在socket.io中,它可能看起来像这样:

var io = require('socket.io')(80);

// Store all your clients
var clients = {};

// Example: http://socket.io/docs/#using-with-node-http-server

io.on("connection", function (socket)
{
    // Save the client to let other client use it
    clients[socket.id] = socket;

    // Send all the clients except the self client
    sendClient(socket);

    // Client disconnected or connection somehow lost
    socket.on("disconnect", function ()
    {
        // Remove the client
        delete clients[socket.id];
    });

    // Simple event to proxy to another client
    socket.on("proxy", function (client)
    {
        if (clients[client.id])
            clients[client.id].emit("event", client.data);
    });
});

// Send all the clients and exclude the given socket id
function sendClient(socket)
{
    var list = [];

    for (let socketId in clients)
    {
        if (!clients.hasOwnProperty(socketId))
            continue;

        if (socketId == socket.id)
            continue;

        list.push(socketId);
    }

    socket.emit("clients", list);
}

,客户端可以(使用socket-io.client):

var io = require('socket.io-client');

var socket = io("http://localhost:80");

socket.on("connect", function ()
{

});

socket.on("clients", function (clients)
{
    // We have all the clients

    clients.forEach(function (clientId)
    {
        var client = {};
        client.id = clientId;
        client.data = {blah: 1};

        socket.emit("proxy", client);
    });
});

socket.on("disconnect", function ()
{

});

答案 1 :(得分:0)

您必须将连接存储在某个位置,例如在数组中(如果您有两个以上)或键入某种唯一标识符的对象,您可以使用它来轻松查找目标套接字。例如:

group by

如果你的应用需要更灵活,你可以使它更复杂。例如,您可以通过在连接时从源套接字读取一行(由<ScrollView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/scrollView" > <include android:layout_height="match_parent" android:layout_width="match_parent" layout="@layout/your_current_layout_for_profile_without_list_view" /> <ListView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/listView" /> </ScrollView> 终止)来找到目标套接字,其中包含目标套接字的IP地址。然后,您可以在每个套接字的IP地址上键入一个对象,而不是数组,这样您就可以轻松找到合适的目标套接字。

或者你可能每个源套接字都发送一个&#34;用户ID&#34;和请求的目的地&#34;用户ID。&#34;此时,您可以将初始单行设为JSON字符串,后跟<ScrollView android:id="@+id/scrollView" android:layout_width="wrap_content" android:layout_height="wrap_content"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"> <View android:layout_width="1dp" android:layout_height="40dp" android:layout_marginBottom="4dp" android:layout_marginLeft="25dp" android:layout_marginRight="20dp" android:layout_marginTop="4dp" android:background="#c0c0c0" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:orientation="vertical"> <ImageView android:layout_width="35dp" android:layout_height="35dp" android:layout_gravity="center" android:layout_marginBottom="4dp" android:src="@drawable/touch" /> <TextView android:id="@+id/mynumofposts" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="200" android:textStyle="bold" /> </LinearLayout> <View android:layout_width="1dp" android:layout_height="40dp" android:layout_marginBottom="4dp" android:layout_marginLeft="20dp" android:layout_marginRight="25dp" android:layout_marginTop="4dp" android:background="#c0c0c0" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:orientation="vertical"> <ImageView android:layout_width="40dp" android:layout_height="40dp" android:layout_gravity="center" android:layout_marginBottom="4dp" android:src="@drawable/nearbycircle" /> <TextView android:id="@+id/mynumoffollowers" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="300" android:textStyle="bold" /> </LinearLayout> </LinearLayout> <ListView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/myprofilelist"/> </ScrollView> ,这样客户端就可以发送任意数量的参数来实现桥接。

使用JSON标头的更复杂解决方案的示例:

var sockets = [];
net.createServer(function(s) {
  // Add the socket to our connected socket list
  sockets.push(s);

  // Automatically remove the socket when it disconnects
  s.on('close', function() {
    sockets.splice(sockets.indexOf(s), 1);
  });

  // How you determine the destination socket is up to you
  var destSocket = ...;

  // This pipes data between the current socket and the
  // destination socket (both directions) but does not automatically
  // close one socket when the other socket closes
  s.pipe(destSocket, { end: false })
   .pipe(s, { end: false });
}).listen(port);

上述解决方案的示例客户端:

\n

此客户端连接后(假设已标识为\n的另一个套接字已连接),目标套接字应该看到数据var sockets = Object.create(null); net.createServer(function(s) { s.on('error', function(err) { }); readJSON(s, function(err, result) { var dest; // Check if socket closed while reading our JSON header if (!s.writable) return; // Immediately close the socket when either: // * We receive a malformed JSON header // * Or the source socket id is already used // * Or the destination socket is not connected // You could extend this check more if you wanted, for example // to perform authentication. if (err || typeof result !== 'object' || result === null || (typeof result.id !== 'string' && typeof result.id !== 'number') || (typeof result.destId !== 'string' && typeof result.destId !== 'number') || sockets[result.id] || !(dest = sockets[result.destId]) || dest.busy) return s.destroy(); var id = result.id; sockets[id] = s; // Set a flag on each socket to allow exclusive communication // between connected sockets s.busy = dest.busy = true; // Hook the sockets up together, allowing the closing of either // socket to close the other s.pipe(dest).pipe(s); s.on('close', function() { delete sockets[id]; }); }); }).listen(port); function readJSON(s, cb) { var buf = ''; (function read() { var chunk = s.read(); if (chunk === null) return s.once('readable', read); for (var i = 0; i < chunk.length; ++i) { // 10 === LF (\n) if (chunk[i] === 10) { // Check if there is leftover data that is not // a part of our JSON message that we need to // put back onto the socket if (i < (chunk.length - 1)) s.unshift(chunk.slice(i + 1)); buf += chunk.toString('utf8', 0, i); var result = tryParseJSON(buf); if (result instanceof Error) cb(result); else cb(null, result); return; } } buf += chunk.toString('utf8'); // TODO: implement `buf.length` check to make sure we don't // buffer indefinitely })(); } // This is merely an optimization since v8 currently does not // optimize any functions containing a `try-catch` or `try-finally`. // By isolating the `try-catch` needed for JSON parsing, we can limit // the deoptimization. function tryParseJSON(str) { try { return JSON.parse(str); } catch (ex) { return ex; } } 。之后,两个插座都将关闭。