Napisałem kod do rozgłaszania wiadomości do wszystkich użytkowników:
// websocket and http servers
var webSocketServer = require('websocket').server;
...
...
var clients = [ ];
var server = http.createServer(function(request, response) {
// Not important for us. We're writing WebSocket server, not HTTP server
});
server.listen(webSocketsServerPort, function() {
...
});
var wsServer = new webSocketServer({
// WebSocket server is tied to a HTTP server.
httpServer: server
});
// This callback function is called every time someone
// tries to connect to the WebSocket server
wsServer.on('request', function(request) {
...
var connection = request.accept(null, request.origin);
var index = clients.push(connection) - 1;
...
Proszę zauważyć:
- Nie mam żadnych odniesień użytkownika, ale tylko połączenie.
- Wszystkie połączenia użytkowników są przechowywane w pliku
array
.
Cel : Powiedzmy, że serwer Node.js chce wysłać wiadomość do określonego klienta (Jana). Skąd serwer NodeJs wiedział, jakie połączenie ma Jan? Serwer Node.js nawet nie zna Johna. wszystko, co widzi, to połączenia.
Tak, wierzę, że teraz, nie należy przechowywać tylko przez użytkowników, ich połączenia, zamiast, muszę zapisać obiekt, który będzie zawierał userId
i ten connection
obiekt.
Pomysł:
Po zakończeniu ładowania strony (DOM ready) - nawiąż połączenie z serwerem Node.js.
Gdy serwer Node.js zaakceptuje połączenie - wygeneruj unikalny ciąg i wyślij go do przeglądarki klienta. Przechowuj połączenie użytkownika i unikatowy ciąg w obiekcie. na przykład
{UserID:"6", value: {connectionObject}}
Po stronie klienta, kiedy ta wiadomość dotrze - przechowuj ją w ukrytym polu lub pliku cookie. (dla przyszłych żądań do serwera NodeJs)
Gdy serwer chce wysłać wiadomość do Jana:
Znajdź identyfikator użytkownika jana w słowniku i wyślij wiadomość przez odpowiednie połączenie.
proszę zauważyć, że nie ma tu wywoływanego kodu serwera asp.net (w mechanizmie wiadomości). tylko NodeJs. *
Pytanie:
Czy to właściwa droga?
źródło
SOCKETS = {};
po stronie serwera i dodać do listy gniazdo dla ID dawać, czyliSOCKETS["John"] = [];
iSOCKETS["John"].push(conn);
. Prawdopodobnie będziesz tego potrzebować, ponieważ użytkownik może otworzyć wiele kart.Oto proste prywatne / bezpośrednie wiadomości na serwerze czatu.
package.json
{ "name": "chat-server", "version": "0.0.1", "description": "WebSocket chat server", "dependencies": { "ws": "0.4.x" } }
server.js
var webSocketServer = new (require('ws')).Server({port: (process.env.PORT || 5000)}), webSockets = {} // userID: webSocket // CONNECT /:userID // wscat -c ws://localhost:5000/1 webSocketServer.on('connection', function (webSocket) { var userID = parseInt(webSocket.upgradeReq.url.substr(1), 10) webSockets[userID] = webSocket console.log('connected: ' + userID + ' in ' + Object.getOwnPropertyNames(webSockets)) // Forward Message // // Receive Example // [toUserID, text] [2, "Hello, World!"] // // Send Example // [fromUserID, text] [1, "Hello, World!"] webSocket.on('message', function(message) { console.log('received from ' + userID + ': ' + message) var messageArray = JSON.parse(message) var toUserWebSocket = webSockets[messageArray[0]] if (toUserWebSocket) { console.log('sent to ' + messageArray[0] + ': ' + JSON.stringify(messageArray)) messageArray[0] = userID toUserWebSocket.send(JSON.stringify(messageArray)) } }) webSocket.on('close', function () { delete webSockets[userID] console.log('deleted: ' + userID) }) })
Instrukcje
Aby to przetestować, uruchom,
npm install
aby zainstalowaćws
. Następnie, aby uruchomić serwer czatu, uruchomnode server.js
(lubnpm start
) w jednej zakładce Terminal. Następnie na innej karcie Terminala uruchomwscat -c ws://localhost:5000/1
, gdzie1
jest identyfikator użytkownika łączącego się. Następnie, w trzeciej zakładce Terminal uruchomićwscat -c ws://localhost:5000/2
, a następnie, aby wysłać wiadomość od użytkownika2
, aby1
wprowadzić["1", "Hello, World!"]
.Niedociągnięcia
Ten serwer czatu jest bardzo prosty.
Trwałość
Nie przechowuje wiadomości w bazie danych, takiej jak PostgreSQL. Dlatego użytkownik, do którego wysyłasz wiadomość, musi być połączony z serwerem, aby ją odebrać. W przeciwnym razie wiadomość zostanie utracona.
Bezpieczeństwo
To jest niepewne.
Jeśli znam adres URL serwera i identyfikator użytkownika Alicji, mogę podszyć się pod Alicję, tj. Połączyć się z serwerem jako ona, co pozwala mi na otrzymywanie jej nowych wiadomości przychodzących i wysyłanie wiadomości od niej do dowolnego użytkownika, którego identyfikator użytkownika również znam. Aby było bezpieczniej, zmodyfikuj serwer, aby akceptował token dostępu (zamiast identyfikatora użytkownika) podczas łączenia. Następnie serwer może uzyskać identyfikator użytkownika z tokena dostępu i uwierzytelnić Cię.
Nie jestem pewien, czy obsługuje połączenie WebSocket Secure (
wss://
), ponieważ przetestowałem go tylko nalocalhost
i nie jestem pewien, jak bezpiecznie się połączyćlocalhost
.źródło
Dla osób korzystających z
ws
wersji 3 lub nowszej. Jeśli chcesz skorzystać z odpowiedzi udzielonej przez @ ma11hew28, po prostu zmień ten blok na następujący.webSocketServer.on('connection', function (webSocket) { var userID = parseInt(webSocket.upgradeReq.url.substr(1), 10)
webSocketServer.on('connection', function (webSocket, req) { var userID = parseInt(req.url.substr(1), 10)
ws
pakiet przeniósł upgradeReq, aby zażądać obiektu i możesz sprawdzić poniższe łącze, aby uzyskać dalsze szczegóły.Źródła: https://github.com/websockets/ws/issues/1114
źródło
Chciałbym podzielić się tym, co zrobiłem. Mam nadzieję, że nie marnuje czasu.
Utworzyłem tabelę bazy danych zawierającą identyfikator pola, adres IP, nazwę użytkownika, czas logowania i czas wylogowania. Kiedy użytkownik loguje się na konto, czas logowania będzie aktualny unixtimestamp unix. A gdy połączenie zostanie nawiązane, baza danych Websocket sprawdza najdłuższy czas logowania. Zostanie zalogowany użytkownik.
A gdy użytkownik się wyloguje, zapisze aktualny czas wylogowania. Użytkownik stanie się tym, kto opuścił aplikację.
Za każdym razem, gdy pojawia się nowa wiadomość, identyfikator Websocket i adres IP są porównywane i wyświetlana jest powiązana nazwa użytkownika. Poniżej znajduje się przykładowy kod ...
// when a client connects function wsOnOpen($clientID) { global $Server; $ip = long2ip( $Server->wsClients[$clientID][6] ); require_once('config.php'); require_once CLASSES . 'class.db.php'; require_once CLASSES . 'class.log.php'; $db = new database(); $loga = new log($db); //Getting the last login person time and username $conditions = "WHERE which = 'login' ORDER BY id DESC LIMIT 0, 1"; $logs = $loga->get_logs($conditions); foreach($logs as $rows) { $destination = $rows["user"]; $idh = md5("$rows[user]".md5($rows["time"])); if ( $clientID > $rows["what"]) { $conditions = "ip = '$ip', clientID = '$clientID' WHERE logintime = '$rows[time]'"; $loga->update_log($conditions); } } ...//rest of the things }
źródło
ciekawy post (podobny do tego, co robię). Tworzymy API (w języku C #) do łączenia dozowników z WebSockets, dla każdego dystrybutora tworzymy ConcurrentDictionary przechowujący WebSocket i DispenserId, ułatwiając każdemu Dispenserowi utworzenie WebSocket i późniejsze używanie go bez problemów z wątkami (wywoływanie określonych funkcji w WebSocket, takich jak GetSettings lub RequestTicket). Różnica w twoim przykładzie polega na użyciu ConcurrentDictionary zamiast tablicy do izolowania każdego elementu (nigdy nie próbowałem tego robić w javascript). Z poważaniem,
źródło