Diskuze: TcpClient<>TcpListener komunikace

C# .NET .NET (C# a Visual Basic) TcpClient<>TcpListener komunikace American English version English version

Avatar
Elisse
Člen
Avatar
Elisse:

Zdravím, pracuji na client - server aplikaci a pro komunikaci používám normálně stringy dekódované na byte[] a ty posílám, nicméně bych se rád zeptal co použít pro přenos jednoduchých řídících signálů. jako např, že se má prostě jen na serveru spustit jedna metoda atp.

Mám prostě posílat přes to spojení např jedno zakódované int číslo? Prakticky mi na strašně serveru staří obdržet "číslo třeba 0-255" a na to si můžu nastavit 256 různých reakcí, ale zajímá mě jestli je to v pořádku řešení nebo je nějaké mnohem lepší a přitom není o moc těžší :)

Díky moc! :)

 
Odpovědět 27. září 16:52
Avatar
Lukas C#
Redaktor
Avatar
Odpovídá na Elisse
Lukas C#:

Nevím jestli to není moc OOP overkill, ale já bych si vytvořil abstraktní třídu Message (která nic neobsahuje).
Z ní pak mohou dědit třídy jako ControlMessage nebo TextMessage, které budou obsahovat vhodné vlastnosti (jak říkáš číslo nebo text). Tyto třídy pak serializuješ ( Binární serializace vrací bajtové pole) a odešleš. Na straně příjemce poté deserializuješ do třídy Message, a uděláš rozhodovací logiku dle typu té Message:

if(message is ControlMessage)
...
else if(message is TextMessage)
...
Akceptované řešení
+20 Zkušeností
+1 bodů
Řešení problému
 
Nahoru Odpovědět  +1 27. září 17:15
Avatar
ostrozan
Redaktor
Avatar
Odpovídá na Elisse
ostrozan:

Záleží na tom, jestli ta řídící informace je vázaná na ten konkrétní string.
Pak bych ji zakomponoval do něj - třeba hned jako první bajt a pak na straně příjmu switchem rozhodnout co s ním.
Pokud ale jsou řídící povely a data na sobě nezávislé, tak bych asi použil něco co popisuje Lukas

 
Nahoru Odpovědět 28. září 6:11
Avatar
Elisse
Člen
Avatar
Odpovídá na Lukas C#
Elisse:

Jo oba co říkáte zní asi dobře :) Druhá otázka je jestli je todle řešení správné. Je v pořádku to řešit todle řízení a zároveň dotazy na server obyčejnýmy čísly?

Jednoduchý příklad server bude clientovi posílat aktuální datum když si ho client vyžádá. Jak by měl vypadat takový požadavek? Nejjednodušší mi prostě přijde, že client pošle jen třeba int číslo 1 a server bude v podmínkách vědět (if IncomingRequest == 1, tak poslat zpátky datum). Ale už na první pohled mi to nepřijde moc elegantní řešení zvlášť když bude mít server v řádech stovek funkcí.

 
Nahoru Odpovědět 29. září 10:10
Avatar
Marian Benčat
Redaktor
Avatar
Marian Benčat:

Je to zcela standardní řešení.. nemáš tam ale v kodu číslo ale prostě konstanty.. Máš prostě něco čemu se říká packet protocol a v něm máš takhle nadefinované jednotliví packety.. tam se ale pak řeší různé optimalizace, které jsou o binárních operacích atd atd.. ;-) Je to poměrně rozsáhlá látka.. které bych se ale možná v tvém případě prvoplánově nevěnoval a udělal to cestou nejmenšího odporu.

 
Nahoru Odpovědět 29. září 10:48
Avatar
Marian Benčat
Redaktor
Avatar
Marian Benčat:

Za sebe ti můžu doporučit se kouknout třeba na eAthena server emulator.. je to emulator pro MMORPG hru, na kterem jsem spolupracoval a právě síťařinu a threading má opravdu na pěkné úrovni. Je to sice Céčko, ale pointu v tom najdeš.

 
Nahoru Odpovědět 29. září 10:49
Avatar
Elisse
Člen
Avatar
Odpovídá na Marian Benčat
Elisse:

Tak to, že je to standartní řešení mě celkem těší. Takže základní věci zredukuju na jednoduché integery a na větší záležitosti použiju serializaci třídy jak poradil kolega nahoře.

Hehe Ragnarok Online :) Threading na štěstí asi nebudu muset řešit, stačí mi vše synchronní a requesty odesílat jak za sebou přijdou :) Ale na tu síťařinu možná mrknul díky za tip :)

 
Nahoru Odpovědět 29. září 12:26
Avatar
Elisse
Člen
Avatar
Odpovídá na Marian Benčat
Elisse:

Aha tak kecám zjistil jsem, že vlákna budou potřeba pokud nebudu chtít po každé zprávě ukončovat spojení :D

 
Nahoru Odpovědět 30. září 11:38
Avatar
Marian Benčat
Redaktor
Avatar
Marian Benčat:

Pokdu to má být něco jako herní server, tak stejně budeš potřebovast connecitonless přístup :-) Ono není úplně ideální na long-term věci mít otevřeno 100 connectionu :-)

 
Nahoru Odpovědět 30. září 15:17
Avatar
Elisse
Člen
Avatar
Odpovídá na Marian Benčat
Elisse:

Co myslíš tím "connecitonless přístup" ? :)

 
Nahoru Odpovědět 30. září 15:19
Avatar
Marian Benčat
Redaktor
Avatar
Marian Benčat:

UDP například.

 
Nahoru Odpovědět 30. září 15:21
Avatar
Elisse
Člen
Avatar
Odpovídá na Marian Benčat
Elisse:

Hmm to bohužel nepůjde, neposílám nic vhodného na UDP, jinak říkáš, že je lepší když člověk potřebuje TCP, tak ty spojení radši uzavírat? :-O Já právě to zrovna přepisoval aby každý client měl spojení dokud se sám neodpojí a ne aby se co každých x zpráv dělalo nové :D

 
Nahoru Odpovědět 30. září 15:39
Avatar
Elisse
Člen
Avatar
Odpovídá na Lukas C#
Elisse:

Nakonec jsem to udělal přesně jak říkáš, z počátku jsem se toho bál, ale předávat si hotové třídy je mnohokrát "hezčí" :)

Nicméně se potýkám s problémem deserializace na druhé straně která přijme serializovanou třídu.

Konkrétně jde o vyjímku:

An unhandled exception of type 'System.Runtime.Serialization.SerializationException' occurred in mscorlib.dll
Additional information: Sestavení ConsoleApplication3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null nebylo nalezeno.

Dočetl jsem se na netu, že je třeba aby měli projekty nějaké společné reference, a ne jen tu stejnou definici třídy, můžete mě prosím navést? :)

Editováno 3. října 11:28
 
Nahoru Odpovědět 3. října 11:27
Avatar
Marian Benčat
Redaktor
Avatar
Marian Benčat:

K tomu, aby bylo možné tyto věci deserializovat, musíš mít assembly, kde je ten typ definovat s metadaty.

Ty definice těch zpráv dej do nějaké class library "Shared" nebo "Contracts". Na to si nareferencuj server a klienta.

 
Nahoru Odpovědět 3. října 12:28
Avatar
Elisse
Člen
Avatar
Elisse:

Jestli jsem tě správně pochopil, tak jen napíšu DLL třeba ve kterém budou definice všech objektů které budu chtít posílat a to DLL bude používat i server i client, ano? :)

 
Nahoru Odpovědět 3. října 14:03
Avatar
Marian Benčat
Redaktor
Avatar
Marian Benčat:

jo a priste reaguj.. at se mi ukaze notifikace.

 
Nahoru Odpovědět 3. října 14:28
Avatar
Elisse
Člen
Avatar
Odpovídá na Marian Benčat
Elisse:

vyjímečně jsem zapomněl :) jdu to testnout

 
Nahoru Odpovědět 3. října 14:32
Avatar
Elisse
Člen
Avatar
Odpovídá na Marian Benčat
Elisse:

No dokonalost už to běží jak má a vesele si posílám structury :) Moc děkuji!! Bohužel druhé řešení ti nedám :)

ještě jen taková otážečka, myslíš, že je lepší poslat více menších tříd/struktur nebo jednu obrovskou? Hádám, že kvůli TCP je lepší poslat rovnou jednu větší, ne?

 
Nahoru Odpovědět 3. října 14:40
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 18 zpráv z 18.