Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: ntpt 14. 05. 2017, 22:50:35
-
Dobrý den.
Snažím se proniknout do node.js a socket.io a z některých věcí nejsem trochu moudrý. Vezměme jejich příklad s jednoduchou chat aplikací.Ten je celkem srozumitelný.
Ovšem jsem v koncích, když přemýšlím, jak to propojit s externími aplikacemi.
Když už jsme u jejich kódu chatovací aplikace:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
chápu že si pomocí require vytvořím express framework objekt, v jeho rámci objekt http serveru (a ten někam bindnu), v rámci serveru si vytvořím objekt io, reprezentující websocket, (víceméně matrjoška) jakmile se na něj někdo připojí vznikne socket
A v jeho rámci reaguji na události - socket.on("událost", function(blah){udělejněco})
io.on('connection', function(socket){
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
Řekněme že se připojí součastzně Franta a Pepa. Chápu, že jejich spojení a jejich websockety nepromíchají neb každé patří do jiné instance objektu socket z jejich příkladu. Řekněme, že si Franta i Pepa vymění nějaké autorizační zprávy ze serverem a tedy bude jasné kdo je na kterém socketu.
Problém začíná, když potřebuji přes takto navázané spojení poslat klientovi data z jiného běžícího programu.Řekněme, že něco běžícího na serveru dojde k názoru, že potřebuje poslat zprávu Pepovi.
Otázklou je JAK to propojit. Zkrátka čím a jak "vstoupit" dovnitř těch vnořených objektů (a do toho správného) a říci (vyvolat událost): ted pošli TYTO data.
Hloupého kopni.... Umí mi prosím někdo vyplnit toto bílé místo ? Děkuji.
-
objekt socket si ulož do nějaké mapy (users.push({"pepa", socket})). Vytvoř si další express server na jiném portu a do něj si posílej informace z tvoji aplikace jako http požadavek, projdi mapu připojených socketů a podle tvých podmínek pošli data na klienta.
Snad pomůže i bez kód, na mobilu se mi špantě píše. Rád bych ale varoval, že podobným přístupem si do aplikace zaneseš spusty bezpečnostních chyb.
-
objekt socket si ulož do nějaké mapy (users.push({"pepa", socket})). Vytvoř si další express server na jiném portu a do něj si posílej informace z tvoji aplikace jako http požadavek, projdi mapu připojených socketů a podle tvých podmínek pošli data na klienta.
Snad pomůže i bez kód, na mobilu se mi špantě píše. Rád bych ale varoval, že podobným přístupem si do aplikace zaneseš spusty bezpečnostních chyb.
users.push({"pepa", socket}) má dělat co? Nemělo to být users["pepa"] = socket ? Jinak máte pravdu.
-
objekt socket si ulož do nějaké mapy (users.push({"pepa", socket})). Vytvoř si další express server na jiném portu a do něj si posílej informace z tvoji aplikace jako http požadavek, projdi mapu připojených socketů a podle tvých podmínek pošli data na klienta.
Snad pomůže i bez kód, na mobilu se mi špantě píše. Rád bych ale varoval, že podobným přístupem si do aplikace zaneseš spusty bezpečnostních chyb.
Ono nevadí že to users.push budu volat uvnitř té matrjožky a ono se mi popropaguje do jiné matrjožky ?? Myslel bych si, že právě tohle nejde, že jsou to vlastně closury vložené do sebe a tedy z principu jedna druhé do kontextu nevidí...
-
objekt socket si ulož do nějaké mapy (users.push({"pepa", socket})). Vytvoř si další express server na jiném portu a do něj si posílej informace z tvoji aplikace jako http požadavek, projdi mapu připojených socketů a podle tvých podmínek pošli data na klienta.
Snad pomůže i bez kód, na mobilu se mi špantě píše. Rád bych ale varoval, že podobným přístupem si do aplikace zaneseš spusty bezpečnostních chyb.
Ono nevadí že to users.push budu volat uvnitř té matrjožky a ono se mi popropaguje do jiné matrjožky ?? Myslel bych si, že právě tohle nejde, že jsou to vlastně closury vložené do sebe a tedy z principu jedna druhé do kontextu nevidí...
users je globální proměnná. Na začátku napiš var users = {}
-
zprávu uživateli pošleš takto
users[username].send(data, callback)
je to zjednodušené, asi budeš ověřovat jestli spojení existuje.
-
jestli tedy dobře chápu: vložit objekt socket do pole - globální proměnné, a použít jej v jiné matrjožce třeba připojené na zmq nebo redis. Principiálně
var users;
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
io.on('connection', function(socket){
socket.on('username', function(username){
users[username]=socket; // ano já vím nebezpečné
};
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
var zmq = require('zeromq')
, sock = zmq.socket('pull');
sock.connect('tcp://127.0.0.1:3000');
console.log('Worker connected to port 3000');
sock.on('message', function(msg){
jakmile dostanu ze zmq zprávu
PODLE OBSAHU ZPRAVY VYBER, kterému spojení poslat,
třeba pomocí JSON.parse(msg) atd získat ze zprávy username a data a ty pak poslat
users[username].send(data, callback);
;
});
takhle nějak ?
-
jestli tedy dobře chápu: vložit objekt socket do pole - globální proměnné, a použít jej v jiné matrjožce třeba připojené na zmq nebo redis. Principiálně
var users;
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
io.on('connection', function(socket){
socket.on('username', function(username){
users[username]=socket; // ano já vím nebezpečné
};
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
var zmq = require('zeromq')
, sock = zmq.socket('pull');
sock.connect('tcp://127.0.0.1:3000');
console.log('Worker connected to port 3000');
sock.on('message', function(msg){
jakmile dostanu ze zmq zprávu
PODLE OBSAHU ZPRAVY VYBER, kterému spojení poslat,
třeba pomocí JSON.parse(msg) atd získat ze zprávy username a data a ty pak poslat
users[username].send(data, callback);
;
});
takhle nějak ?
v principu je to správně.
nevím co znamená matrjožka kromě dřevěné hračky. V kontextu nodejs jsem to nikdy neslyšel.
users by měl být objekt, tedy var users = {}.
Bezpečnější by asi bylo použít sessionid namísto username. Případně ověřovat, že zpráva přišla z originu, na kterou se může dostat jen danný uživatel.
Zeromq je asi dobrý nápad. Dá se použít i http na nějakém portu neviditelném zvenku.
-
ano, nadřazené proměnné se propagují do těch vnitřních. Nejedná se o globální proměnné, btw.
Použití pole místo objektu byl ode mě jen krok napřed (users je poté nutné inicializovat jako var user = []). Mohu mít uživatele s více okny prohlížeče, chci mu to tedy poslat asi do všech nebo v době vytvoření připojení nemám k dispozici ještě jméno uživatele, tak musím ukládat sessionId a to je pak mnohem efektivnější procházet a hledat v poli než v objektu.
Je tady poté i další aspekt, pokud uživatelské jméno je vstupem z venku a já ho dávám jako klíč do objektu, mohu si s tím zadělat na problém, kdy správně zvolená jména mi odrovnají aplikaci kvůli složitosti jejich hledání v hashmapě.
Další drobnost je třeba performance, pokud budu do pole ukládat pořád stejný objekt, JIT v JS s ním bude pracovat velice efektivně. Mazání nebo přidávání položek do pole je i při velkém množství takových operací stabilní. Dělat tohle s objektem, mohu si zadělat na dost nepříjemné bugy nebo memory leaky.
-
matrjožka jako přirovnání, že jsou jednotlivé objekty do sebe zanořeny jeden v druhém jako ty panenky jedna do druhé expres(http(io(connection(socket(on({})))))) je jedna matrjožka. zmq( sock (on({})) ) je dhuhá..
Zkrátka jako ilustraci zapouidření instancí objektů do sebe.
Jinak samozřejmě tohle byl příklad, kde bezpečnost nebyla řešená neb šlo o princip. Samozřejmě v reálu je nutno použít patřičné mechanizmy jak se daný klient autorizuje atd....
-
ano, nadřazené proměnné se propagují do těch vnitřních. Nejedná se o globální proměnné, btw.
Použití pole místo objektu byl ode mě jen krok napřed (users je poté nutné inicializovat jako var user = []). Mohu mít uživatele s více okny prohlížeče, chci mu to tedy poslat asi do všech nebo v době vytvoření připojení nemám k dispozici ještě jméno uživatele, tak musím ukládat sessionId a to je pak mnohem efektivnější procházet a hledat v poli než v objektu.
Je tady poté i další aspekt, pokud uživatelské jméno je vstupem z venku a já ho dávám jako klíč do objektu, mohu si s tím zadělat na problém, kdy správně zvolená jména mi odrovnají aplikaci kvůli složitosti jejich hledání v hashmapě.
Další drobnost je třeba performance, pokud budu do pole ukládat pořád stejný objekt, JIT v JS s ním bude pracovat velice efektivně. Mazání nebo přidávání položek do pole je i při velkém množství takových operací stabilní. Dělat tohle s objektem, mohu si zadělat na dost nepříjemné bugy nebo memory leaky.
Vyhledávání v hashmapě je rychlejší než v poli. Pokud potřebujete řešit víc spojení pro jednoho usera, musíte to dělat pomocí hashmapy polí.
var users = {};
.....
if(users[userid]){
users[userid].push(connection);
}else{
users[userid] = [connection];
}
-
ano, nadřazené proměnné se propagují do těch vnitřních. Nejedná se o globální proměnné, btw.
Jaký je mezi tím a globální proměnnou rozdíl ?
Použití pole místo objektu byl ode mě jen krok napřed (users je poté nutné inicializovat jako var user = []). Mohu mít uživatele s více okny prohlížeče, chci mu to tedy poslat asi do všech nebo v době vytvoření připojení nemám k dispozici ještě jméno uživatele, tak musím ukládat sessionId a to je pak mnohem efektivnější procházet a hledat v poli než v objektu.
Je tady poté i další aspekt, pokud uživatelské jméno je vstupem z venku a já ho dávám jako klíč do objektu, mohu si s tím zadělat na problém, kdy správně zvolená jména mi odrovnají aplikaci kvůli složitosti jejich hledání v hashmapě.
samozřejmě tohle je rychlopříklad mechanizmu, v reálu by spoléhal že uživatel je skutečně ten jehož username mi pošle prohlížeč , bez žádné autentizace, vytvoření sessiony či nějakého ekvivalentu etc , asi jen šílenec.
Další drobnost je třeba performance, pokud budu do pole ukládat pořád stejný objekt, JIT v JS s ním bude pracovat velice efektivně. Mazání nebo přidávání položek do pole je i při velkém množství takových operací stabilní. Dělat tohle s objektem, mohu si zadělat na dost nepříjemné bugy nebo memory leaky.
díky za užitečný tip..
-
users.push({"pepa", socket})
je syntakticky špatně, proto jsem se ptal, co to má dělat. Asi jste chtěl napsat {"pepa":socket}.
-
ano, nadřazené proměnné se propagují do těch vnitřních. Nejedná se o globální proměnné, btw.
Jaký je mezi tím a globální proměnnou rozdíl ?
je to atribut objektu global, ale to je IMHO to stejné co globální proměnná.
-
Je tady poté i další aspekt, pokud uživatelské jméno je vstupem z venku a já ho dávám jako klíč do objektu, mohu si s tím zadělat na problém, kdy správně zvolená jména mi odrovnají aplikaci kvůli složitosti jejich hledání v hashmapě.
to je blbost. Složitost vyhledávání v hashmapě nemůže být horší než vyhledávání v poli, i kdyby útočník měl možnost vytvořit jména všech uživatelů.
-
Je tady poté i další aspekt, pokud uživatelské jméno je vstupem z venku a já ho dávám jako klíč do objektu, mohu si s tím zadělat na problém, kdy správně zvolená jména mi odrovnají aplikaci kvůli složitosti jejich hledání v hashmapě.
to je blbost. Složitost vyhledávání v hashmapě nemůže být horší než vyhledávání v poli, i kdyby útočník měl možnost vytvořit jména všech uživatelů.
Coz je potencialne dost na problem...
-
Coz je potencialne dost na problem...
existuje příklad podobného útoku? Ani jsem nikde nenašel příklad konfliktních klíčů. Když vám útočník vytvoří tisíce podvodných účtů, tak budete mít problém i při ukládání do pole.
-
Děkuji všem za odpovědi. Ještě by mě ovšem zajímala jedna věc. Reentrantnost , součastný běh či serializovatenost callbacků.
z přikladu:
socket.on('chat message', function(msg){
UDELEJ NECO CO TRVÁ DLOUHO
};
co se stane, když callback ještě běží... a dojde další "chat message" ? běží paralerně ? čeká se na dokončení toho prvního ? Nebo co vlastně ?
-
Děkuji všem za odpovědi. Ještě by mě ovšem zajímala jedna věc. Reentrantnost , součastný běh či serializovatenost callbacků.
z přikladu:
socket.on('chat message', function(msg){
UDELEJ NECO CO TRVÁ DLOUHO
};
co se stane, když callback ještě běží... a dojde další "chat message" ? běží paralerně ? čeká se na dokončení toho prvního ? Nebo co vlastně ?
V JS se tupě multiplexuje na jedno vlákno, takže typicky se čeká (blokuje), než callback doběhne. Když něco trvá dlouho, tak by se měl použít další callback, aby se ty kusy kódu proložily.
-
Ty nejsi node zacatecnik, ty si dev zacatecnik, mazej si koupit knihu a neprud na foru. Vsude se dozvis ze js je single thread async jazyk, tak proboha proc se tady ptas jestli muzou bezet callbacky paralelne...
A taky prosim nepouzivej novotvary jako treba matrjoska, jediny co tim druhymu cloveku reknes je to ze si mozna rusak.
-
Ty nejsi node zacatecnik, ty si dev zacatecnik, mazej si koupit knihu a neprud na foru. Vsude se dozvis ze js je single thread async jazyk, tak proboha proc se tady ptas jestli muzou bezet callbacky paralelne...
A taky prosim nepouzivej novotvary jako treba matrjoska, jediny co tim druhymu cloveku reknes je to ze si mozna rusak.
Učený z nebe nespadl. Ale pitomce jako by shazovali. Jak je vidět na vašem případě.
-
Děkuji všem za odpovědi. Ještě by mě ovšem zajímala jedna věc. Reentrantnost , součastný běh či serializovatenost callbacků.
z přikladu:
socket.on('chat message', function(msg){
UDELEJ NECO CO TRVÁ DLOUHO
};
co se stane, když callback ještě běží... a dojde další "chat message" ? běží paralerně ? čeká se na dokončení toho prvního ? Nebo co vlastně ?
Neběží paralelně. Proto můžeš bez obav použít ten slovník spojení. Čumil má pravdu, udělal bys lépe, kdyby sis nejdřív prošel nějaký tutorial k javascriptu. Většina tutorialů k nodejs znalost javascriptu a souvisejícího názvosloví předpokládá.
-
V JS se tupě multiplexuje na jedno vlákno, takže typicky se čeká (blokuje), než callback doběhne. Když něco trvá dlouho, tak by se měl použít další callback, aby se ty kusy kódu proložily.
P.S. Vývojáři knihoven v JS by udělali dobře, kdyby začali používat korutiny (když už je novější JS má), aby ušetřili sobě i uživatelům těch knihoven spoustu problémů s callbacky.
-
Děkuji všem za odpovědi. Ještě by mě ovšem zajímala jedna věc. Reentrantnost , součastný běh či serializovatenost callbacků.
z přikladu:
socket.on('chat message', function(msg){
UDELEJ NECO CO TRVÁ DLOUHO
};
co se stane, když callback ještě běží... a dojde další "chat message" ? běží paralerně ? čeká se na dokončení toho prvního ? Nebo co vlastně ?
Neběží paralelně. Proto můžeš bez obav použít ten slovník spojení. Čumil má pravdu, udělal bys lépe, kdyby sis nejdřív prošel nějaký tutorial k javascriptu. Většina tutorialů k nodejs znalost javascriptu a souvisejícího názvosloví předpokládá.
A víte, že mi těch cca 20 příspěvků, kdy se zeptám na věci které mne zajímají, dalo více než deset tutoriálů ? Máte pravdu, nejsem žádný javascriptový guru, zatím jsme si vystačil jen s událostmi v prohlížeči, víc jseM nepotřeboval. Teď potřebuju. Tak krom toho že "čtu tutorialy", tak se ptám.
Ptali jste se všichni velcí vývojáři, když jste v čemkoliv začínali, a vsadím se že i vám lidé kteří měli zkušenosti poradili i v tom, co museli vidět jako úplmné základy. Narážky typu kup si knihu a nepruď jsou značně offtopic. A jestli je někdo pyšný a zakládá si na svých vědomostech a s toho důvodu, aby to druhý neměl moc snadné, se nechce podělit, snadná pomoc NEMUSÍ ODPOVÍDAT.
-
A víte, že mi těch cca 20 příspěvků, kdy se zeptám na věci které mne zajímají, dalo více než deset tutoriálů ? Máte pravdu, nejsem žádný javascriptový guru, zatím jsme si vystačil jen s událostmi v prohlížeči, víc jseM nepotřeboval. Teď potřebuju. Tak krom toho že "čtu tutorialy", tak se ptám.
Ptali jste se všichni velcí vývojáři, když jste v čemkoliv začínali, a vsadím se že i vám lidé kteří měli zkušenosti poradili i v tom, co museli vidět jako úplmné základy. Narážky typu kup si knihu a nepruď jsou značně offtopic. A jestli je někdo pyšný a zakládá si na svých vědomostech a s toho důvodu, aby to druhý neměl moc snadné, se nechce podělit, snadná pomoc NEMUSÍ ODPOVÍDAT.
Javascript v prohlížeči také nespouští nic souběžně. while(true){}; zablokuje stránku. V nodejs to funguje stejně.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop
-
A víte, že mi těch cca 20 příspěvků, kdy se zeptám na věci které mne zajímají, dalo více než deset tutoriálů ?
Přesně tak, zeptat se na základy není ostuda. A odpovídající nemusí dávat najevo svou nadřazenost - pokud někoho dotazy na základy obtěžují, tak přece nemusí odpovídat.
Je sice pravda, že k osvojení základních pojmů a principů by mělo sloužit oficiální vzdělání, ale jak víme, praxe je často taková, že se člověk učí vše až za pochodu. Proto dobrých zdrojů, které to vzdělání kvalitně doplní, není nikdy dost.
-
Přesně tak, zeptat se na základy není ostuda. A odpovídající nemusí dávat najevo svou nadřazenost - pokud někoho dotazy na základy obtěžují, tak přece nemusí odpovídat.
Je sice pravda, že k osvojení základních pojmů a principů by mělo sloužit oficiální vzdělání, ale jak víme, praxe je často taková, že se člověk učí vše až za pochodu. Proto dobrých zdrojů, které to vzdělání kvalitně doplní, není nikdy dost.
Mně nevadí, když se někdo ptá. Rád se pokusím odpovědět. Z vlastní zkušenosti je rychlejší si projít začátečnické kapitoly a nepřeskakovat je.
Nejde o oficiální vzdělání. Javascript se do nedávna na školách nevyučoval. Node.js je nová technologie. Zboj je Phd., a Javascript také nezná.
-
A víte, že mi těch cca 20 příspěvků, kdy se zeptám na věci které mne zajímají, dalo více než deset tutoriálů ?
Přesně tak, zeptat se na základy není ostuda. A odpovídající nemusí dávat najevo svou nadřazenost - pokud někoho dotazy na základy obtěžují, tak přece nemusí odpovídat.
Je sice pravda, že k osvojení základních pojmů a principů by mělo sloužit oficiální vzdělání, ale jak víme, praxe je často taková, že se člověk učí vše až za pochodu. Proto dobrých zdrojů, které to vzdělání kvalitně doplní, není nikdy dost.
Tak od toho jsou fóra. Problém je, že na otázky odpovídají lidi, co o tom taky nic neví (a co hůř, myslí si opak). Node.js znám například skrznaskrz a v čemkoliv rád poradím, ale to, co tu občas člověk čte za bláboly, je k neuvěření. Chce-li se někdo něco dozvědět, měl by jít na stackoverflow.
-
Tak od toho jsou fóra. Problém je, že na otázky odpovídají lidi, co o tom taky nic neví (a co hůř, myslí si opak). Node.js znám například skrznaskrz a v čemkoliv rád poradím, ale to, co tu občas člověk čte za bláboly, je k neuvěření. Chce-li se někdo něco dozvědět, měl by jít na stackoverflow.
Nikdo ti nebrání odpovědět lépe.
-
Dobrý den.
Snažím se proniknout do node.js a socket.io a z některých věcí nejsem trochu moudrý. Vezměme jejich příklad s jednoduchou chat aplikací.Ten je celkem srozumitelný.
Ovšem jsem v koncích, když přemýšlím, jak to propojit s externími aplikacemi.
Když už jsme u jejich kódu chatovací aplikace:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
chápu že si pomocí require vytvořím express framework objekt, v jeho rámci objekt http serveru (a ten někam bindnu), v rámci serveru si vytvořím objekt io, reprezentující websocket, (víceméně matrjoška) jakmile se na něj někdo připojí vznikne socket
A v jeho rámci reaguji na události - socket.on("událost", function(blah){udělejněco})
io.on('connection', function(socket){
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
Řekněme že se připojí součastzně Franta a Pepa. Chápu, že jejich spojení a jejich websockety nepromíchají neb každé patří do jiné instance objektu socket z jejich příkladu. Řekněme, že si Franta i Pepa vymění nějaké autorizační zprávy ze serverem a tedy bude jasné kdo je na kterém socketu.
Problém začíná, když potřebuji přes takto navázané spojení poslat klientovi data z jiného běžícího programu.Řekněme, že něco běžícího na serveru dojde k názoru, že potřebuje poslat zprávu Pepovi.
Otázklou je JAK to propojit. Zkrátka čím a jak "vstoupit" dovnitř těch vnořených objektů (a do toho správného) a říci (vyvolat událost): ted pošli TYTO data.
Hloupého kopni.... Umí mi prosím někdo vyplnit toto bílé místo ? Děkuji.
Systémové řešení jen mít prostě API pro IPC a onen objekt registrovat. IPC pak bude běžet nezávisle a posílat data dle potřeby. Koncepčně čisté řešení jsou například kanály (CSP), i když zrovna v JS se CSP implementuje dost blbě.
-
Systémové řešení jen mít prostě API pro IPC a onen objekt registrovat. IPC pak bude běžet nezávisle a posílat data dle potřeby. Koncepčně čisté řešení jsou například kanály (CSP), i když zrovna v JS se CSP implementuje dost blbě.
Řešení neexistujícího problému.