Java týden
30 % bodů zdarma na online výuku díky naší Slevové akci!
Pouze tento týden sleva až 80 % na e-learning týkající se Javy.

Diskusia: C# TCP server někdy odešle zprávu se zbytky předchozí zprávy

Aktivity (4)
Avatar
lukas.sei
Člen
Avatar
lukas.sei:1. augusta 11:00

Dobrý den,
Pracuju teď na jedné aplikaci na PC, která bude komunikovat přes TCP s několika arduino klienty. Aplikace má sloužit jako "herní server" tzn. očekává nějakou zprávu od arduina a násladně mu na ni má odpovědět.
Problém však nastává v té komunikaci.. Server mi sem tam odešle zpět zprávu, která obsahuje ještě část zprávy předchozí a tudíž klient neví co s takovou zprávou dělat.

Ukázky špatných odpovědí jsou v obrázku.

Zde je zdroják mého TCP Serveru: https://www.itnetwork.cz/…lighter/1350

Skúsil som: Zkoušel jsem nejdřív všechny stringy používané pro uchování zprávy před odesláním vynullovat, ale bez úspěchu. Dále jsem zkoušel po odeslání zavolat NetworkStream­.Flush(); ale také bez žádného úspěchu. (Co jsem pochopil, tak tahle funkce zatím nic nedělá a je pouze rezervovaná dobudoucna)

Chcem docieliť: Server by měl odpovídat následovně:
Přijatá zpráva od klienta: "CNN:1"
odpověď: "CNN:1:CFM"

Přijatá zpráva od klienta: "PONG"
odpověď: "PING"

Přijatá zpráva od klienta: "CHGTM:1:B"
odpověď: "CHGTM:1:B:CFM" nebo "CHGTM:1:GMPAUSED" (podle toho, jestli je hra pozastavena nebo spuštěna)

a jednou za čas by server sám od sebe měl odeslat zprávu "PING" pro ověření, že je klient stále dostupný.

 
Odpovedať
1. augusta 11:00
Avatar
lukas.sei
Člen
Avatar
lukas.sei:1. augusta 16:30

ještě mě napadlo, že bych každou zprávu mohl ukončit speciálním znakem např "!" a následně ji v arduinu rozdělit. Tím bych z tama mohl nepoužitelné fragmenty vyřadit.

Pokud má někdo lepší nápad tak sem s ním vítám jakékoliv řešení.

 
Hore Odpovedať
1. augusta 16:30
Avatar
Odpovedá na lukas.sei
Ing. Petr Štechmüller:2. augusta 7:55

Ahoj, pošlu nám ještě kód klienta.

Hore Odpovedať
2. augusta 7:55
Pokud spolu kód a komentář nekorespondují, budou patrně oba chybné
Avatar
lukas.sei
Člen
Avatar
lukas.sei:2. augusta 9:20

Ahoj, Jako TCP klienta momentálně na zkoušení funkčnosti využívám Android aplikaci TCP Client a Windows Aplikaci Hercules.

 
Hore Odpovedať
2. augusta 9:20
Avatar
Jahnny
Člen
Avatar
Jahnny:4. augusta 8:46

Ahoj. Problem je v tom, ze jedna tvoja odoslana sprava moze byt zabalena do viacerych TCP paketov, preto pri citani dostavas neuplne casti. Na .Net urovni je najefektivnesie (ak nie aj jedine) riesenie posielat si nejaky START pripadne STOP znak (skupinu znakov). Potom jednoducho cyklicky citas a spravy si rozdelujes podla tychto znakov (vies ze si ju precital celu).

 
Hore Odpovedať
4. augusta 8:46
Avatar
Odpovedá na lukas.sei
Erik Šťastný:5. augusta 15:02

Zasekl jsi se na stejném problému, který mě děsně trápil když jsem já poprvé začal s TCP :)

Je to přesně jak píše Jahnny nademnou.
Read ani write ti vůbec negarantuje, že pošleš nebo přečteš přesně ten počet bytů co chceš. Je třeba to například číst opakovaně dokud nebudeš spokojený.

Možnost je například jak píše Jahnny, ale je jich víc.
Já například si implementovat to, že se vždy pošlou 4 bajty které obsahují integer kolik dalších bajtů je zpráva kterou musím přečíst.

Editované 5. augusta 15:03
 
Hore Odpovedať
5. augusta 15:02
Avatar
Erik Šťastný:5. augusta 16:16

Tady máš přesně topic ve kterém jsem se na to ptal :) Můžeš si to pročíst.

https://stackoverflow.com/…-of-messages

 
Hore Odpovedať
5. augusta 16:16
Tento výukový obsah pomáhajú rozvíjať nasledujúce firmy, ktoré možno hľadajú práve teba!
Avatar
lukas.sei
Člen
Avatar
Odpovedá na Erik Šťastný
lukas.sei:5. augusta 22:34

Děkuji mockrát za odpověď :)

Momentálně mám systém vyřešený tak, že každou zprávu končím znakem "!". Poté tu zprávu rozdělím právě tímto znakem, přidám si je do listu a jednu po druhé je vyhodnocuji. Zprávy, které nemají správný formát ignoruji. A jako pojistku mám v Arduinu kód, který když do nějaké doby neobdrží odpověď tak zprávu pošle znova.

Zatím to vypadá, že vše šlape tak jak má. Uvidíme jak se to bude chovat když k tomu přidáme pomalejší a méně stabilní připojení :D

 
Hore Odpovedať
5. augusta 22:34
Avatar
Odpovedá na lukas.sei
Erik Šťastný:6. augusta 6:57

U TCP by se ti určitě nemělo nikdy stát, že nějaká zpráva nepřijde. To by znamenalo chybu celého spojení a nutnost jeho znovu vytvoření, nikoliv jen znovu odeslání zprávy. :)

 
Hore Odpovedať
6. augusta 6:57
Avatar
lukas.sei
Člen
Avatar
Odpovedá na Erik Šťastný
lukas.sei:6. augusta 9:45

No ta záloha je tam hlavně z toho důvodu, kdyby nějaká zpráva přišla neuplná. (Například jedna čast by došla na konci Bufferu a druhá část na začátku nového bufferu)

 
Hore Odpovedať
6. augusta 9:45
Avatar
Odpovedá na lukas.sei
Erik Šťastný:6. augusta 13:15

Ty by jsi to ale ideálně měl udělat tak, že ten buffer budeš skládat až dokud nenarazíš na ten tvůj "!" až pak tu zprávu zpracovat :) Takto pokud chápu správně, tam přidáváš haldu zbytečného provozu.

 
Hore Odpovedať
6. augusta 13:15
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Luboš Běhounek Satik:6. augusta 13:47

Oddelovat vykricnikem fungovat muze, pokud se posilaji jen jednoduche stringy, ktere vykricnik obsahovat nemuzou, ale idealni a bezne pouzivane reseni je (jak uz tu bylo zmineno) posilat nejaky header, kde je uvedena delka a typ zpravy a pak cekat, az se precte cela zprava.

Hore Odpovedať
6. augusta 13:47
https://www.facebook.com/peasantsandcastles/
Avatar
lukas.sei
Člen
Avatar
Odpovedá na Erik Šťastný
lukas.sei:6. augusta 21:19

Nad tím už jsem přemýšlel. Napadlo mě, že bych po naplnění bufferu mohl ten buffer uložit do stringu. String pak rozdělit vykřičníkem, odebrat z něj uplné zprávy, zbytek v něm nechat a následně k tomu zbytku přidat obsah dalšího bufferu. Akorát si momentálně nějsem jistý jak udělat tu část "odebrat ze stringu".

No do budoucna určitě přemýšlím nad tím to udělat tímto způsobem, zvlášť když budu do té aplikace přidávat další funkce, ale momentálně to asi plánuju nechat takto. Přece jenom ty stringy které jsou odesílané jsou docela jednoduché a nemají moc variací.

 
Hore Odpovedať
6. augusta 21:19
Avatar
Odpovedá na lukas.sei
Erik Šťastný:6. augusta 21:23

Něco takového asi můžeš. Zkrátka zacykly ten read na tak dlouho, dokud nebudeš mít i ten vykřičník :)

Nicméně lepší je podle mě jak píše Luboš, udělat si ty hlavičky. Pak přesně víš kolik bajtů máš přečíst a neřešíš to až podle dat obsažených v bajtech.

 
Hore Odpovedať
6. augusta 21:23
Robíme čo je v našich silách, aby bola tunajšia diskusia čo najkvalitnejšia. Preto do nej tiež môžu prispievať len registrovaní členovia. Pre zapojenie sa do diskusie sa zaloguj. Ak ešte nemáš účet, zaregistruj sa, je to zadarmo.

Zobrazené 14 správy z 14.