• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Node.js WebSocket - identyfikacja klienta

Object Storage Arubacloud
0 głosów
784 wizyt
pytanie zadane 21 lutego 2017 w JavaScript przez Zainteresowany Nowicjusz (240 p.)
Witajcie, mam pewien problem..

Mam bazę w której trzymam informacje o graczach, m. in. ich ID, zycie, poziom itd.

Na serwerze w node.js postawiony mam serwer WebSocket. Skąd mam wiedzieć jaką daną z bazy danych mam przesłać do danego klienta?

Wcześniej gdy robiłem to w php to przy logowaniu w sesji ustawiałem zmienną sesyjną ID uzytkownika odpowiadającą danemu hasłu i loginowi i na jej podstawie wczytywałem odpowiednie dane z bazy np. SELECT zycie FROM baza WHERE ID=14.

Jak poradzić sobie z tym wykorzystując webSockety i node.js?

1 odpowiedź

0 głosów
odpowiedź 24 lutego 2017 przez crool Użytkownik (960 p.)
wybrane 25 lutego 2017 przez Zainteresowany
 
Najlepsza

Rozwiązanie jest proste, zmień bazę danych na mongodb, jest to baza danych, która przechowuje dane w formacie JSON, np. 

{
 życie: 100,
 poziom: 50, 
 nick: 'crool'
}

przy dodawaniu nowego obiektu, w tym przypadku użytkownika mongodb automatycznie nadaje obiektowi swój identyfikator (ObjectId)

Do pracy z mongodb szczególnie polecam moduł mongoose, masz tutaj przykład kodu: 

const mongoose = require('mongoose'); // definujesz obiekt reprezentujący modul
mongoose.connect('mongodb://localhost:27017/'); //łączysz z bazą danych

let userModel = new mongoose.Schema({ //tworzysz nowy schemat przechowywania danych
 lvl: Number, //podajesz nazwe klucza i rodzaj np. Number, String, Array
 hp: Number, 
 nick: String
},{
 collection: 'users' //nazwa kolekcji
});
let userModelToUse = mongoose.model('users', userModel);
io.on('newUser', (user) => {
 let newUser = new userModelToUse({ //tworzysz nowy obiekt oparty na schemacie, dane jak lvl możesz pobrać z socketów
  lvl: user.lvl,
  hp: user.hp,
  nick: user.nick
  });
 newUser.save(); //nastepnie zapisujesz usera w bazie
});

io.on('findUser', (userId) => {
 userModelToUse.findById(userId, (err, results) => { //szukasz usera 
  //result to twój user :)
 });
});

Myślę, że zrobiłem żadnego błędu, polecam dokumentacje mongoose, tam dowiesz się więcej

PS
W czym robisz gierke? Jak chcesz mogę Ci pokazać moją w nodejs po stronie serwera i canvasie po stronie clienta, pozdrawiam

 

komentarz 25 lutego 2017 przez Zainteresowany Nowicjusz (240 p.)
edycja 25 lutego 2017 przez Zainteresowany

Witaj, nie spodziewałem się, że ktoś odpisze po tylu dniach, dlatego nie zaglądałem tutaj. Dzięki za odpowiedź.

Ogarniam od rana MongoDB. Rzeczywiście jest to świetna alternatywa dla MySQL, bardzo mi się podoba taka odmiana.

Gry zawsze pisałem w PHP, Teraz jest moje pierwsze podejście do Node.js i MongoDB, dopiero się uczę. Najwięcej problemów sprawia mi asynchroniczność funkcji w Node.js. Niby rozumiem na czym to polega ale na każdym kroku napotykam na ograniczenia i nie mogę albo nie wiem jak osiągnąć zamierzony efekt. Jeśli zechciałbyś mi czasami coś podpowiedzieć albo naprowadzić na właściwy sposób to byłbym bardzo wdzięczny. 

Póki co zrobiłem routing za pomocą Express. Ogarnąłem silnik Jade i nauczyłem się tworzyć sesje przy pomocy modułów express-session i body-parser. Przeczytałem sporą część dokumentacji. 

Logowanie rozwiązałem w taki sposób:

app.post('/logowanie',function(req,res){
  	sess = req.session;
	db.collection('gracze').find( { login: req.body.login, haslo: req.body.password } , { _id : 0 } ).toArray(function(err, results) {
		if(results.length == 1) {
  		    sess.login = req.body.login;
  		    res.render('Gra.html');
  		} else {
  			res.render('logowanie.html', {error: true});
  		}
	});
});

Myślisz, że jest to w miarę poprawne czy można to zrobić lepiej?

Problem w tej chwili mam z rejestracją nowych użytkowników..

Po wysłaniu formularza muszę sprawdzić szereg rzeczy. Przeprowadzam walidację wprowadzonych danych, np czy login ma odpowiednią długość, czy oba hasła są identyczne itd. Ale oprócz tego muszę sprawdzić czy istnieje już w bazie podany login albo email. Robię to tak:

db.collection('gracze').find( {$or: [ { login: req.body.login }, { email: req.body.email } ] }, {login: 1, email: 1 } ).toArray(function(err, results) {
walidacjaZaliczona = true;
//Chciałbym tutaj sprawdzić czy obiekt result zawiera req.body.login lub req.body.email
//Jak mam to zrobić? W PHP zrobiłbym to tak:
if(results.indexOf(req.body.login) > -1) {
//login istnieje w zwróconym result z bady danych
//ustawiam zmienną errorLogin na true
walidacjaZaliczona = false;
}
if(results.indexOf(req.body.email) > -1) {
//email istnieje w zwróconym result z bady danych
//ustawiam zmienną errorEmail na true
walidacjaZaliczona = false;
}
//Pozostałe sprawdzenia, np długość loginu, poprawnosc maila, zgodność haseł itd
//
if(​​​​​​​walidacjaZaliczona) {
    //dodaję nowego uzytkownika do bazy
}
});

Jak mam to zrobić w Node.js? Jeśli chcę wykorzystać jakąś funkcję np contains albo indexOf to muszę znowu robić to asynchronicznie, i przez to wszystko staje się mało czytelne i mocno zagnieżdzone, dodatkowo tracę dostęp do zmiennych ustawionych wcześniej podczas walidacji danych. Gubię się w tej asynchroniczności i nie wiem jak się rozwiązuje w node takie problemy. Podpowiedziałbyś coś? Zacząłem czytać książkę "Node.js w praktyce Tworzenie skalowalnych aplikacji sieciowych" ale trudno mi nadążyć za tym co tam piszą.

komentarz 25 lutego 2017 przez crool Użytkownik (960 p.)

Po pierwsze zobacz sobie moduł mongoose, ułatwi on Ci znacznie pracę z MongoDb, a jeżeli chodzi o walidacje to jest taki moduł express-validator, posiada on wbudowane funkcje sprawdzania długości znaków, czy jakaś wartość jest pusta, a nawet czy jest email jest poprawny. Jeżeli chodzi o wbudowane funkcje typu indexOf to polecam moduł lodash, posiada on naprawdę sporą ilość funkcji do obiektów tablic. Również czytałem Node.js w praktyce i szczerze powiem, że ta książka nie jest zbyt dobra pod względem kodu, jest w większości przypadków przestarzały, ale jeżeli chodzi o wyjaśnienie samej asynchroniczności i zagadnienia teoretyczne to jest solidna.

/*O ile dobrze pamiętam to results jest tablicą więc
możesz po prostu sprawdzić czy ma ona długość większą niż 0,
ponieważ jeżeli już taki użytkownik istnieje to będzie on w tej tablicy*/
if(results.length > 0){
 return false;
 //lub walidacjaZaliczona = false;
}
/*poza tym polecam najpierw sprawdzić czy hasła są takie same i login ma odpowiednią 
długość, bo po łączyć się z bazą danych na próżno, zabiera to czas i moc obliczeniową */

if(req.body.length > 4 || req.body.password == req.body.configPassword){
 //łączysz z bazą
}else {
 return false;
}

 

komentarz 25 lutego 2017 przez Zainteresowany Nowicjusz (240 p.)
edycja 25 lutego 2017 przez Zainteresowany

Fajnie, że chciało Ci się znowu tutaj do mnie zajrzeć. Odnośnie tego return.. Przecież nie da się zwrócić niczego z funkcji asynchronicznej? Jak próbuję przypisać ją do zmiennej i zwrócić coś za pomocą return to zawsze wynik to undefined albo Function. Może coś źle rozumiem?

 

A co do rejestracji to zrobiłem w międzyczasie i działa. Wklejam kod, mógłbyś ocenić czy tak się pisze w node czy źle to wszystko robię?

app.post('/rejestracja',function(req,res) {
  	var dane = true;
  	var errLogin = false;
  	var errEmail = false;
  	var errPassword = false;
  	var errRegulamin = false;

  	if(req.body.login.length < 3 || req.body.login.length > 10) {
  		dane = false;
  		errLogin = "Login musi posiadać od 3 do 10 znaków";
  	}
  	if(!(/^[a-z0-9]+$/i.test(req.body.login))) {
  		dane = false;
  		errLogin = "Login musi składać się z liter i cyfr (bez polskich znaków)";
  	}
  	if(!(/^\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$/.test(req.body.email))) {
  		dane = false;
  		errEmail = "Podaj poprawny adres email";
  	}
  	if(req.body.pass1.length < 8 || req.body.pass1.length > 20) {
  		dane = false;
  		errPassword = "Hasło musi posiadać od 8 do 20 znaków";
  	}
  	if(req.body.pass1 != req.body.pass2 ) {
  		dane = false;
  		errPassword = "Podane hasła nie są identyczne";
  	}
  	if(!req.body.regulamin) {
  		dane = false;
  		errRegulamin = "Zaakceptuj regulamin";
  	}

	db.collection('gracze').find( { login: req.body.login }, { _id : 1 } ).toArray(function(err, results) {
		if(results.length >= 1) {
			dane = false;
  			errLogin = "Podany login jest zajęty";
		}
		db.collection('gracze').find( { email: req.body.email }, { _id : 1 } ).toArray(function(err, results) {
			if(results.length >= 1) {
				dane = false;
	  			errEmail = "Podany email jest zajęty";
			}

			if(dane) {
				db.collection('gracze').insert( { login: req.body.login, email: req.body.email, haslo: req.body.pass1 }, function(err, results) {
					res.send('Założono konto');
				});
			} else {
		  		res.render('rejestracja.html', {errorLogin : errLogin, errorEmail : errEmail, errorPassword: errPassword, errorRegulamin: errRegulamin, errorCaptcha: errCaptcha, tempLogin: req.body.login, tempEmail: req.body.email});	
			}
		});
	});
});

A co do tego co mi poradziłeś to już zabieram się za czytanie o tych modułach o których pisałeś. Skoro są to postaram się z nich korzystać ;)

 

EDIT:

Tak teraz pomyślałem, że przed łączeniem się z bazą mogę sprawdzać aktualną wartość zmiennej dane. Jeśli jest true czyli cała walidacja poszła pomyślnie to łączę się z bazą i sprawdzam dostępność Loginu i Maila, w przeciwnym wypadku zwracam formularz z informacjami o błędach i nie wykonuję łączenia z bazą.

 

komentarz 25 lutego 2017 przez crool Użytkownik (960 p.)

Ja zrobiłbym to w ten sposób: 

function check(email, login, password){
 if(){
 return false;
 //tutaj te wszystkie ify
}
 return true; // jezeli funkcja cos zwara to przestaje sie wykonywac, wiec jezeli dotrwala ona do tego momentu to znaczy, ze nic wczesniej nie zostalo zwrocone (zaden if sie nie wykonal)
}

app.post('/rejestration', (req, res, next) => {
 if(check(req.body.email, req.body.login, req.body.password)){
  //sprawdzasz co zwrocila funkcja check, jezeli true to laczysz sie z baza danych 
 }else {
  //jezeli zwrocila false to renderujesz sobie strone z bledem
  //luknij sobie jeszcze na modul flash, nie bedziesz musial renderowac strony za kazdym razem z bledem
 }
})

 

Wszystko jest dobrze, ale połowę rzeczy, które tu napisałeś są zbędne, tzn można je zastąpić funkcjami z modułu lodash i express validator, tak wgl jaka grę tworzysz, coś typu mmorpg czy plemiona ?

PS

Pamiętaj, że funckja, która coś zwraca, traktowana jest jako wartość, to bardzo ważne 

komentarz 25 lutego 2017 przez Zainteresowany Nowicjusz (240 p.)
Dzięki, już się zabieram za przerobienie tego w taki sposób jak mówisz.

Co do gry to piszę coś w rodzaju Plemion, zwykłe proste klikanie i rozwijanie postaci.

Zawsze takie rzeczy pisałem w PHP, jquery, Ajax ale doszedłem do wniosku, że trzeba się rozwijać i spróbować czegoś nowego. Zwłaszcza, że chciałbym wykorzystywać WebSockety do tworzenia elementów w grze działających w czasie rzeczywistym.

Wspominałeś wcześniej o swojej grze i o tym, że mógłbyś pokazać kod. Jeśli to aktualne to chętnie bym obejrzał, pewnie dużo bym się nauczył.

Dzięki jeszcze raz, biorę się do pracy.
komentarz 25 lutego 2017 przez crool Użytkownik (960 p.)
WebSockety to dobra technologia, o wiele szybsza od ajaxa, ale zobaczysz jaki problem będzie przy autoryzacji :)

Co do mojej gry, to mogę Ci pokazać, podaj mi jakiegoś maila to Ci kod wyśle i powiem Ci jak ją odpalić, bo o dziwo nie odpala się jej z poziomu przeglądarki tylko aplikacji, ale wciąż pisze w javascript html i css, zobacz sobie platforme electron
komentarz 13 kwietnia 2017 przez spamator12 Nałogowiec (28,230 p.)

Najwięcej problemów sprawia mi asynchroniczność funkcji w Node.js. Niby rozumiem na czym to polega ale na każdym kroku napotykam na ograniczenia i nie mogę albo nie wiem jak osiągnąć zamierzony efekt.

 

Nie tylko tobie :)

 

Podobne pytania

0 głosów
0 odpowiedzi 191 wizyt
pytanie zadane 25 marca 2016 w C# przez mje Nowicjusz (120 p.)
0 głosów
2 odpowiedzi 626 wizyt
pytanie zadane 18 maja 2015 w JavaScript przez marianexyx Nowicjusz (120 p.)
+1 głos
0 odpowiedzi 342 wizyt
pytanie zadane 28 grudnia 2021 w JavaScript przez qax Dyskutant (8,060 p.)

92,570 zapytań

141,422 odpowiedzi

319,643 komentarzy

61,958 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...