8

ホームページに Web ソケットを必要としないが、他の相対パス (「/new」など) には必要とする Web サイトがあるとします。

「ホーム」ページと「新しい」ページにログインするユーザーをカウントするために、「接続」イベントが必要だとします。

次のような相対パスでsocket.ioの「接続」イベントを構成しようとしました:

app.get('/new',
         function(req,res) {
              io.sockets.on('connection', function (socket) {
                .....
              }
         });

しかし:

  1. うまく機能しません。多くのユーザーが接続すると、そのイベントが発生してはならないときに発生します。
  2. 上記のようなウェブ上の例は見当たりませんでした。すべての socket.io イベントは、メイン ファイル (app.js) で 1 回構成されます。

どうすればできますか?

4

3 に答える 3

18

質問への回答:

  1. 明らかに、ユーザーが/newそのハンドラーをヒットすると、ハンドラーが起動し、接続ハンドラーが に追加されるためioです。それは巨大なメモリリークです。

  2. それは上記のものに関連しています。ユーザーが にアクセスするたびに接続ハンドラを追加したくない/new場合。

今あなたの問題を解決するために、私は最善のアイデアは(ブラウザ側で)呼び出すことだと思います

io.connect("http://localhost/new");

次に、Node.js アプリで次のようにします。

io.of("/new").on("connection", function (socket) {
    // here are connections from /new
});

コードは、ルート ハンドラー内ではなく、最上位に配置する必要があります。より動的にしたい場合は、独自のサブプロトコルを作成できます。

  1. io サーバーに接続します: io.connect("http://localhost);
  2. メッセージを送信しますI'm in /new
  3. サーバーでそのメッセージを取得し、その接続を適切なリストに保存します。

もちろん、クライアントを socket.io サーバーに接続するかどうかをルート ハンドラーで指定できます (単に何らかのフラグを渡すだけです)。

于 2013-09-03T15:21:47.103 に答える
1

Socket.io 接続は、そのようなハンドラー メソッドで初期化されません。
ページがレンダリングされ、ブラウザがクライアント側スクリプトをロードし、io.connect が (クライアント側スクリプトで) 呼び出された後に初期化されます。

サーバー側スクリプトの任意の場所で io.sockets.on('connection') を呼び出すと、別のリスナー (サーバー リスナー) をソケット接続イベントに登録するだけです。
リクエスト ハンドラーに配置すると、'/new' に GET リクエストを送信するたびに、別のリスナーが登録されます。(console.log をそこに置き、更新を数回押して、新しいソケットがいつ接続されるかを確認できます)

一部のページでsocket.io接続が必要ない場合は、次のようにすることができます

サーバーサイドスクリプトで

app.all("*", function(req, res, next) {
    res.locals({
        needSocketIo: true
    });
}

app.get('/some-page-you-do-not-want-socket-io', function(req, res) {
    res.render('some-view', {needSocketIo: false});
})

ビュー/レイアウトでは、socket.io ロジックに javascript ファイルを含めるか含めないかは、if/else 句にすぎません。

また、サーバーにソケットの接続元を知らせたい場合は、クライアントからメッセージを送信できます

socket.on('connect', function () {
    socket.emit('from', {page: 'your-page'});
});
于 2013-09-03T15:24:47.330 に答える
0

socket.ioクライアントをページごとに選択的に配置することを選択しない場合は、承認イベントを使用して、接続元のページを確認できます。

io.configure(function () {
  io.set('authorization', function (handshakeData, callback) {
    if (handshakeData.url == '/new') {
      //allow the socket to connect
      callback(null, true);
    } else {
      //prevent the socket handshake with an error
      callback('socket.io is not accepting connections from this page', false);
    }
  });
});

コードでは、誰かがそのページをロードするたびio.sockets.onにイベントにリスナーを追加しているため、オブジェクトを複数回使用しないでください。connectionさらに、ハンドシェイクが拒否された場合、connectionイベントは決して発生しないため、次のようなセットアップを使用できます。

io.sockets.on('connection', function(socket) {
  //this shouldn't ever happen, it's the same object that was checked before
  if (socket.handshake.url != '/new') {
    socket.disconnect();
    return;
  }

  //do something on page '/new'
}

app.get('/new', function(req, res) {
  //sockets can successfully connect with this page
});

app.get('/foo', function(req, res) {
  //sockets from this page will fail handshakes and be disconnected
});

ページ上のユーザー数をカウントする必要がある場合は、ソケットの接続イベントと切断イベントの両方をリッスンします。これは、それを行うための 1 つの方法です。

var pages = [];
io.sockets.on('connection', function(socket) {
  if (pages[socket.handshake.url] == null) {
    pages[socket.handshake.url] = 0;
  }
  pages[socket.handshake.url]++;

  socket.on('disconnect', function() {
    pages[socket.handshake.url]--;
  });
}

人々が複数のタブを開いた場合、接続されたセッション Cookie を保存し、オブジェクトを使用して一致を探すことができsocket.handshakeます。

于 2013-09-03T14:55:14.893 に答える