Black Friday Black Friday
Black Friday výprodej! Až 80 % extra bodů zdarma! Více informací zde
Avatar
Erik Šťastný:12. dubna 12:17

Zdravíčko,

děláme na aplikaci s jedním serverem a množtvím klientů a máme již navržený způsob komunikace a rád bych si ho jen nechal zhodnotit někým zkušenějším, jestli má nějaké nevýhody nebo rizika atp.

Takže.... Rozhodli jsme se pro TCP spojení (Využítí TCPClient a TCPListener z .NET)
Jedna jasně definovaná struktura zprávy:

class DecodedMessage
{
    public int id;
    public Dictionary<string, string> data;

    public DecodedMessage(int id, Dictionary<string, string> data)
    {
        this.id = id;
        this.data = data;
    }
}

Zpráva vždy obsahuje ID podle kterého se client nebo server rozhoduje co je to za zprávu a co s ní má vlastně dělat a dále je custom slovník ve kterém je x různých hodnot.

Tento objekt (zpráva) je serializovaný do JSONu a převeden na byte array. Před byte array jsou přidány další 4 byty jako délka původního byte array a odeslán.

Můžete to prosím někdo nějak objektivně zhodnotit? Případně říct jestli je to +- fajn nebo naopak úplně špatně? Děkuji moc :)

Editováno 12. dubna 12:18
 
Odpovědět 12. dubna 12:17
Avatar
Luboš Satik Běhounek
Autoredaktor
Avatar
Luboš Satik Běhounek:12. dubna 12:54

Misto intu muzete pro id pouzit enum, bude to o neco prehlednejsi pri debugovani, pokud ty idcka nemuzou bejt nejak uplne custom a znate je predem.

Jinak server a klient jsou v jinem jazyce nebo je to nejaka jina sluzba? Nebo proc pouzivate json a posilate vsechno jako stringy?

Binarne by to bylo efektivnejsi, ale to uz zalezi na tom, jaky je duvod pro ten json.

Nahoru Odpovědět 12. dubna 12:54
https://www.facebook.com/peasantsandcastles/
Avatar
Odpovídá na Luboš Satik Běhounek
Erik Šťastný:12. dubna 13:03

Jo enum zní dobře, mě nenapadlo :)

Server je C# Console app a client je C# DLLko, které bude použíté v Unity.

Ono zkoušel jsem právě performance json, xml i binary a binary mělo v určitých případech velkých objektů hlavně, horší teď si nejsem jistý, deserializaci tuším než newstone knihovna pro json.

Nicméně performance je asi zanedbatelný, hlavní důvod je asi přehlednost při debugování.

 
Nahoru Odpovědět 12. dubna 13:03
Avatar
Luboš Satik Běhounek
Autoredaktor
Avatar
Odpovídá na Erik Šťastný
Luboš Satik Běhounek:12. dubna 13:20

Binary nikdy nemuze mit vykon horsi nez cokoliv jinyho, to je v podstate jen zkopirovani pameti.

Json musis cislo prevest na nejakou strukturu, cislo se tam musi prevest na string apod., pak to pri cteni rozparsovat na casti jsonu, pak cisla ze stringu...

Hlavne na GC tohle bude vetsi zatez, protoze pri tom bude asi vznikat dost pomocnych objektu, ale jestli ma smysl to resit zalezi na tom, kolik tech zprav tam budete posilat za vterinu, kolik klientu bude pripojenych a jestli nebude bottleneck jinde.

Nahoru Odpovědět  +1 12. dubna 13:20
https://www.facebook.com/peasantsandcastles/
Avatar
Odpovídá na Luboš Satik Běhounek
Erik Šťastný:12. dubna 13:34

Výkonová změna je pravděpodobně zanedbatelná.

Nicméně vím, že jsem to zkoušel s třídou BinaryFormatter a zkoušel jsem až absurdně velké objekty, které se nikdy reálně posílat nebudou a od určité velikosti byl zlom, kde se to šíleně zpomalilo a newstone knihovna byla najednou rychlejší než ta binární, a týkalo se to tuším především deserializace. Serializace byla tuším stále rychlá.

(Objekty se serializovali a deserializovali do souboru na disk)

Každopádně až se komunikace oddebuguje asi nebude problém vyměnit json za binární, proč ne.

Měl by jsi ještě nějaké výtky?

 
Nahoru Odpovědět 12. dubna 13:34
Avatar
Marian Benčat
Redaktor
Avatar
Odpovídá na Erik Šťastný
Marian Benčat:12. dubna 13:58

Můžu mít super debilní otázku? Když chceš komunikovat přes TCP/IP a rovnou serializovat a deserisalizovat JSON, tak proč tedy rovnou nepoužiješ prostě webserver? :D u nového .NET core je ten overhead vůči naprosto primitivní TCP/IP komunikaci minimální a většina věcí je udělána za tebe..

Navíc.. pokud potřeubješ RTC, máš přímo nad .NET CORE SignalR, který má navíc clientské library pro všechny jazyky světa .

Nahoru Odpovědět 12. dubna 13:58
Totalitní admini..
Avatar
Marian Benčat
Redaktor
Avatar
Marian Benčat:12. dubna 14:01

Já jsem třeba byl schopný poměrně na pohodu (z legrace) přepsat kus MMORPG serveru, kde používal pro komunikaci SignalR a žádný problém jsem nezaznamenal (je ale pravda, že tam bylo jen 180 connections v reálném čase)

Nahoru Odpovědět 12. dubna 14:01
Totalitní admini..
Avatar
Odpovídá na Marian Benčat
Erik Šťastný:12. dubna 14:19

No hlavní důvod je, že jsem se s ničím takovým nesetkal a neumím to.

Druhý je ten, že chci přijmout spojení, provést autentizaci, uložit si clienta do listu a kdykoliv na něj moci z konzole poslat nějakou zprávu.
Webserver jsem si vždy představoval spíše v aplikacích (dotaz -> odpověď) i když vím že to dnes již není pravda.

Jinak nepoužívám .NET Core

 
Nahoru Odpovědět 12. dubna 14:19
Avatar
Marian Benčat
Redaktor
Avatar
Odpovídá na Erik Šťastný
Marian Benčat:12. dubna 14:32

No,.. s tcp komunikací zřejmě také ne., když chceš používat JSON.

Poslyše.. i v normálním .net core je signalR.. Ono je to ve svě podstatě strašně primitivní.. 10 řádek kódu a máš realtime komunikaci na serveru..

https://docs.microsoft.com/…lr-self-host

neřešíš nic, serializaci / deserializaci, zpětnou kompatiblitu.. Z pohledu tvého kódu prostě budeš jen volat METODY (ano, tak strašně jednoduše se to používá) a on si ve spod to přeloží na síťovou komunikaci.

Je velmi jednoduché s tím pracovat...

Věnuj tomu 3 hodiny, třeba budeš spokojený? Samozřejmě nikdy nedosáhneš výkonu jako u své vlastní TCP/IP (ideálně UDP) komunikace, ale myslím si, že ti to vystačí bohatě na to co budeš potřebovat..

Nahoru Odpovědět 12. dubna 14:32
Totalitní admini..
Avatar
Marian Benčat
Redaktor
Avatar
Marian Benčat:12. dubna 14:33

https://github.com/…nalR-Unity3d (nevím jeslti je aktuálně použitelné, ale v example vidíš, jak jednoduchéí je to na použití)

Nahoru Odpovědět 12. dubna 14:33
Totalitní admini..
Avatar
Odpovídá na Marian Benčat
Erik Šťastný:12. dubna 14:54

Abych řekl pravdu, trvalo mi celkem dost času naučit se pracovat s TcpListenerem,TcpCli­entem a NetworkStreamy. k tomu pochopit principy async, await pro použití jejich asynchroních method, atp.

Nevím jestli se mi chce to celé zahodit a začít studovat něco jiného :/

 
Nahoru Odpovědět 12. dubna 14:54
Avatar
Marian Benčat
Redaktor
Avatar
Odpovídá na Erik Šťastný
Marian Benčat:12. dubna 17:32

Nj a teď si vem, že to někdo udělal všechno za tebe a napsal třeba SignalR.
nevím jestli si na to koukal.. ale opravdu se to při použití tváří, že "prostě voláš metodu".

Tim ti nechci říct, že nemáš pokračovat v bádání.. určitě pokračuj.

PS.: naprosté minimum .net programátorů opravdu chápu a ví jak funguje async/await. Pokud tomu tak je u tebe, tak všechna čest. U mě tomu předcházelo delší studium a refresh znalostí assembleru a CPU.

Editováno 12. dubna 17:32
Nahoru Odpovědět 12. dubna 17:32
Totalitní admini..
Avatar
Odpovídá na Marian Benčat
Erik Šťastný:12. dubna 17:38

Koukal jsem na to co jsi poslal no, ono ve stejném stavu mám tu svou implementaci.
Prostě jen metody:

SendMessage()
GetMessage()

na clientovi.

Samozřejmě jsem neřekl, že vím do podrobna jak funguje, bylo myšleno ve stylu, že ho umím použít.

Editováno 12. dubna 17:38
 
Nahoru Odpovědět 12. dubna 17:38
Avatar
Martin Dráb
Redaktor
Avatar
Odpovídá na Erik Šťastný
Martin Dráb:12. dubna 22:03

Použití JSONu jako média pro přenos strukturovaných dat, proč ne, pokud nepotřebuješ moc výkonu, nebo ti tak nezáleží na vytížení sítě. S tím také souvisí otázka, zda potřebuješ posílat celé objekty, nebo by třeba stačilo jen nějaké memnší množství dat, ze kterých je na druhé straně zkonstruuješ.

Pak se musíš zamyslet nad tím, jak ten tvůj protokol rozvíjet, tzn. jak uděláš autentizaci, popř. ochranu integrity či šifrování. Nevím, zda signalR tyhle možnosti má (HTTPS nemusí být úplně správná volba, pokud bys často navazoval a ukončoval spojení).

Nahoru Odpovědět 12. dubna 22:03
2 + 2 = 5 for extremely large values of 2
Avatar
Odpovídá na Martin Dráb
Erik Šťastný:13. dubna 9:03

Přesnos "neobjektů" jsem měl udělaný dříve a přišlo mi šílené to udržovat, když jsem potřeboval nový typ zprávy atp. Takhle si do objektu nacpu klíče a hodnoty, které potřebuju a nemusím nic měnit.

Autentizace je řešená tím, že mám loginové ID zprávy, kterým dokud klient neprojde, tak zpátky dostává error zprávy, že není přihlášen a jinou zprávu kromě loginu server odmítne.

Ochranou integrity myslíš co? Hádám, že o vše by se mělo postarat samotné TCP, ne?

Co se týče šifrování, má jít o ne realtimovou hru, kde 100% logiky je na serveru a předpokládám, že ani není důvod něco šifrovat.
Nicméně kdybych přešel z jsonu na samotnou binární serializaci, není to dostatečná ochrana proti tomu kdyby to někdo zkoušel odchytit ty zprávy? Pro nezasvěceného člověka to bude úplný blábol, ne?

 
Nahoru Odpovědět 13. dubna 9:03
Avatar
Odpovídá na Erik Šťastný
Erik Šťastný:13. dubna 9:43

Chyba, vlastně ten login by asi chtělo šifrovat.

 
Nahoru Odpovědět 13. dubna 9:43
Avatar
Martin Dráb
Redaktor
Avatar
Odpovídá na Erik Šťastný
Martin Dráb:13. dubna 14:42

Přesnos "neobjektů" jsem měl udělaný dříve a přišlo mi šílené to udržovat, když jsem potřeboval nový typ zprávy atp. Takhle si do objektu nacpu klíče a hodnoty, které potřebuju a nemusím nic měnit.

To máš pravdu. Dá se to řešit buď dobrým návrhem, ve kterém už obsáhneš všechny potřebné typy zpráv, takže nebudeš dělat časté změny později, nebo třeba generováním kódu pro jejich příjem a odeslání (z nějakého abstraktního popisu).

Autentizace je řešená tím, že mám loginové ID zprávy, kterým dokud klient neprojde, tak zpátky dostává error zprávy, že není přihlášen a jinou zprávu kromě loginu server odmítne.

Jde o to, abych třeba já jako tvůj protihráč se nemohl přihlásit jako někdo jiný a pak ho ve hře poškozovat, jelikož se mi podařilo zachytit samotné přihlašování (heslo šlo v plaintextu), nebo jsem třeba uhodl nějaká ta login ID.

Ochranou integrity myslíš co? Hádám, že o vše by se mělo postarat samotné TCP, ne?

Myslel jsem ochranu proti tomu, aby ti někdo "po cestě" něco do těch paketů přidával, ale uznávám, že to může být dosti hypotetický scénář, pokud se jedná o věc, kde nepředpokládáš velké masy uživatelů.

Co se týče šifrování, má jít o ne realtimovou hru, kde 100% logiky je na serveru a předpokládám, že ani není důvod něco šifrovat.

Ano, může tomu být tak. Pak ti šifrování (krom ochrany integrity, pokud to tam přidáš) zajistí i to, že nikdo nebude moci odpozorovat, jaké ostatní posílají příkazy. Samozřejmě je otázka, jestli to za to stojí. Pro autentizaci šifrování nutně potřeba není, stačí digitální podpisy.

Nicméně kdybych přešel z jsonu na samotnou binární serializaci, není to dostatečná ochrana proti tomu kdyby to někdo zkoušel odchytit ty zprávy? Pro nezasvěceného člověka to bude úplný blábol, ne?

Pro nezasvěceného ano. Ale je možné, že ten formát by třeba šel vykoukat ze zdrojáků .NET Core, Mono či jiných OSS projektů. Případně samozřejmě zreverzit.


Ale dost z těchto věcí řešit nemusíš, pokud se jedná o něco malého – tzn. neočekáváš tak masové využití, že by se problémy, které při ne dobře udělané autentizaci, šifrování atd. vzniknou, začaly zneužívat. Kdyby k tomu došlo, mohl bys mít pak potíže ty mechanismy dovnitř implementovat, neb s nimi původní návrh vlastně nepočítal.

Nahoru Odpovědět 13. dubna 14:42
2 + 2 = 5 for extremely large values of 2
Avatar
Odpovídá na Martin Dráb
Erik Šťastný:13. dubna 15:48

Díky za tipy :)

 
Nahoru Odpovědět 13. dubna 15:48
Avatar
lukasko.simon:16. dubna 16:16

este taky detail... triedy TcpListener a TcpClient boli uz davnejsie marknute Microsoftom ako "obsolete" a odporuca sa pouzivat triedu Socket ktora uz vie pracovat ako klient aj server a pride mi aj ovela jednoduchsia a zrozumitelnejsia ako predchodca

Editováno 16. dubna 16:17
 
Nahoru Odpovědět 16. dubna 16:16
Avatar
Odpovídá na lukasko.simon
Erik Šťastný:16. dubna 16:30

No nevím, ale nepřijde mi moc, že účel TcpListener a TcpClient, kde jejich důvod je právě odstínění od socketové vrstvy pro jednodušší použítí je opačný.

Jinak máš nějaký zdroj? Většinou když je něco obsolete, tak to přímo na msdn je uvedeno, u těchto tříd nic nevidím.

 
Nahoru Odpovědět 16. dubna 16:30
Avatar
lukasko.simon:16. dubna 16:45

beriem spat iba jeden z konstruktorov je ako obsolete. Preco by to malo byt odstinene od socketovej vrstvy? ved tcp komunikacia prebieha prave cez socketovu vrstvu (ip+port) . TcpListener je vpodstate wrapper nad socket triedou, takze ci pouzijes jedno alebo druhe tak ucel to splni no pri TcpListeneri je ta abstrakcia trosku vyssia a nemas az taku siroku moznost konfiguracie ako pri Sockete

 
Nahoru Odpovědět 16. dubna 16:45
Avatar
Odpovídá na lukasko.simon
Erik Šťastný:16. dubna 16:53

Přesně to myslím tím odstíněním... větší abstrakci :)

 
Nahoru Odpovědět 16. dubna 16:53
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 22 zpráv z 22.