2014-04-13 10 views
5

Tôi đang sử dụng Node.js với socket.io cho trò chơi nhiều người chơi và có các phòng trò chơi mà người chơi có thể tham gia.Kiểm tra một dòng nếu ổ cắm nằm trong phòng nhất định?

Đối với việc gia nhập một căn phòng, tôi chỉ đơn giản sử dụng:

io.sockets.on('connection', function (socket) { 
    socket.on('joinRoom', function (gid) { 
     //gid is game ID - create room name based on this and join the room 
     var room = 'game'+gid; 
     socket.join(room); 
    }); 
}); 

Câu hỏi của tôi là, cách nhanh nhất để kiểm tra xem một ổ cắm được kết nối tới một căn phòng nào đó là bao nhiêu? Tôi biết tôi có thể nhận được tất cả các ổ cắm trong phòng đó trong một mảng và sau đó kiểm tra xem các ổ cắm mục tiêu là trong mảng, nhưng tôi đoán phải có một cú pháp cơ bản hơn cho việc này. Những gì tôi đang tìm kiếm (trong mã giả) sẽ là

if(socket with ID "z8b7dbf98i" is in room "game10") 
    //do something 
+0

Hãy thử điều này 'if (_. Has (io.sockets.adapter.rooms [RoomId], socket.id))' –

+0

Xem phần này: https://stackoverflow.com/questions/19044660/socket-io -get-rooms-which-socket-hiện đang ở trong – PallavBakshi

Trả lời

8

Đối với tài liệu, socket.io dường như không có cách nào đơn giản để làm điều đó. Bạn thực sự cần kiểm tra xem client có nằm trong mảng phòng hay không, hoặc ngược lại: nếu phòng nằm trong mảng client.

Điều này có thể được thực hiện với một oneliner sử dụng indexOf:

if(socket.rooms.indexOf(room) >= 0) 

Hoặc tìm kiếm ngược lại:

if(io.sockets.manager.rooms['/' + room].indexOf(socket.id) >= 0) 
+0

Lưu ý rằng khi sử dụng redis để đồng bộ hóa nhiều nút, API khác (không đồng bộ): https://github.com/socketio/socket.io-redis#redisadapterclientsroomsarray- fnfunction –

2

Đối socket.io (1.0 trở lên tôi giả sử) cấu trúc hiện tại của io đối tượng đã được thay đổi, do đó bây giờ bạn có thể tìm ra người dùng có số socketid trong phòng có ổ cắm đã cho roomid bởi:

if(io.sockets.adapter.rooms[roomid][socketid])

+2

Điều này đã thay đổi một lần nữa, bây giờ bạn yêu cầu '' 'if (io.sockets.adapter.rooms [data.groupId] .sockets [socket.id])' '' – Ryan

0

Nếu bạn vẫn cần nó, bạn có thể làm tiếp theo:

socket.room = "someRoom"; 

và sau đó chỉ cần kiểm tra xem nó:

if (socket.room !== undefined){ 
     socket.leave(socket.room); 
    } 
+0

hãy sửa định dạng của bạn bằng cách thụt lề '}' cuối cùng – YakovL

1

này dường như đã thay đổi khá nhiều với các phiên bản của socket. io, nhưng khi viết bài này (phiên bản 1.7.2), có vẻ như nó được lưu trữ trong socket.rooms. Đây là một đối tượng mà trông như thế này:

{ 
    room_name: 'room_name', 
    second_room_name: 'second_room_name', 
    ... 
} 

Trước ổ cắm bạn đã tham gia bất kỳ phòng, như tài liệu, bạn sẽ thấy rằng các ổ cắm đã nằm trong một căn phòng với id riêng của nó, vì vậy socket.rooms sẽ giống như thế:

{ PxtiIs22S7GhWPTSAAAA: 'PxtiIs22S7GhWPTSAAAA'} 

điều đó có nghĩa bạn có thể kiểm tra xem một ổ cắm là trong một cái gì đó phòng như thế này:

io.on('connection', function(socket){ 
    if(socket.rooms[myRoomName]){ 
    // in the room 
    }else{ 
    // not in the room 
    } 
}); 
+0

Có vẻ tên phòng được chuyển thành ** PxtiIs22S7GhWPTSAAAA **. Cho phép 'nói một khách hàng đã tham gia một tên phòng ** Session-Started **. Nó sẽ được lưu trữ dưới dạng {PxtiIs22S7GhWPTSAAAA: 'PxtiIs22S7GhWPTSAAAA'}. Vì vậy, không có cách nào để có được tên phòng đơn giản là tốt. Đúng nếu tôi sai. –

4

bạn chỉ có thể kiểm tra như
này 0.123.io.sockets.adapter.rooms['roomId']

Điều này trả về cho bạn một đối tượng với sId ví dụ:
{"1sEAEIZeuMgdhF35AAAA":true}


cập nhật cụ thể đối với các phiên bản:

1.4+:

io.sockets.adapter.rooms['roomId'] 

1.3.x:

io.sockets.adapter.rooms['roomId']; 

1.0.x đến 1.2.x:

Cập nhật
io.adapter.rooms['roomId']; 


:
Tuy nhiên người ta có thể kiểm tra Id ổ cắm được đặt trong phòng hoặc không có một dòng như đã đề cập ở trên chỉ khi kiến ​​trúc máy chủ có máy chủ nút đơn/quá trình nút đơn.

Nếu bạn đang sử dụng multi-node server, tức là quy trình nút riêng biệt có cân bằng tải.

Điểm cần lưu ý ở đây là, các ổ cắm chỉ được đăng ký trong quá trình mà chúng được kết nối lần đầu tiên. Vì vậy, bạn cần sử dụng socket.io-redis để kết nối tất cả các nút của bạn với nhau để đồng bộ hóa sự kiện và những gì bạn có thể làm để duy trì danh sách các Id ổ cắm trên nhiều nút được phát một sự kiện mỗi khi khách hàng kết nối/ngắt kết nối, để mỗi nút cập nhật & duy trì danh sách thời gian thực của tất cả các Id máy khách/socket.

Bối cảnh/Chi tiết:
Adapter redis mở rộng base adapter, nhưng nó chỉ overrides/adds the following properties:
khách hàng phát sóng thêm del delAll

Với đoạn mã sau:

io.sockets.adapter.rooms["roomId"]; //Any of the above examples specific to versions mentioned above 

bạn là truy vấn thuộc tính phòng trên bộ điều hợp socket.io-redis. Điều này không bị ghi đè bởi bộ điều hợp redis, vì vậy bạn đang thực sự truy vấn bộ điều hợp cơ sở, mà chỉ biết về phòng/khách hàng trong quá trình hiện tại.

Tại sao bộ điều hợp Redis không ghi đè thuộc tính phòng? Có thể là vì nó sẽ phải truy vấn cá thể cơ sở dữ liệu redis để xây dựng một đối tượng có chứa tất cả các phòng và các kết nối trên mọi truy cập của thuộc tính này. Không phải là một ý tưởng tốt?

Vì vậy, khi viết bài này câu trả lời, bạn sẽ có thêm chức năng đó để adapter riêng của mình với một phương pháp như thế này:

/** 
    * One-Line code/property to check if the socket id is in given room. 
    * 
    * @param {String} room id 
    * @param {Function} callback (optional) 
    * @api public 
    */ 

    Redis.prototype.isSidExistsInRoom = function(room, fn){ ... } 

nơi bạn sẽ nhấn database instance redis.

Đây phải là một phần của giao diện bộ điều hợp cơ sở để tất cả các bộ điều hợp khác thực hiện. Đó là vấn đề phổ biến mà mọi người sẽ phải đối mặt trong một ngày, khi họ mở rộng máy chủ của mình;)

P.S. Chỉ cần một gợi ý về cách tiếp cận khác là sử dụng các phương thức customRequest/customHook trong socket.io-redis 3.1.0.


Cập nhật với ver 5.2.0: (liên quan các máy chủ đa node)
adaptor Bây giờ redis mang đến cho bạn phòng qua các quy trình/nút như của 5.2.0
Nguồn: RedisAdapter#clients(rooms:Array, fn:Function)

Trả về danh sách ID khách hàng được kết nối với phòng trên tất cả các nút. Xem Namespace#clients(fn:Function)

io.of('/').adapter.clients((err, clients) => { 
    console.log(clients); // an array containing all connected socket ids 
}); 

io.of('/').adapter.clients(['room1', 'room2'], (err, clients) => { 
    console.log(clients); // an array containing socket ids in 'room1' and/or 'room2' 
}); 

// you can also use 

io.in('room3').clients((err, clients) => { 
    console.log(clients); // an array containing socket ids in 'room3' 
}); 


Chúc mừng Mã hóa!

Các vấn đề liên quan