BF Summer sales
Pouze tento týden sleva až 80 % na HTML & CSS a JavaScript
80 % bodů zdarma na online výuku díky naší Letní akci!

Diskuze: 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. srpna 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

Zkusil jsem: 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)

Chci docílit: 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ý.

 
Odpovědět
1. srpna 11:00
Avatar
lukas.sei
Člen
Avatar
lukas.sei:1. srpna 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í.

 
Nahoru Odpovědět
1. srpna 16:30
Avatar
Odpovídá na lukas.sei
Ing. Petr Štechmüller:2. srpna 7:55

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

Nahoru Odpovědět
2. srpna 7:55
Pokud spolu kód a komentář nekorespondují, budou patrně oba chybné
Avatar
lukas.sei
Člen
Avatar
lukas.sei:2. srpna 9:20

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

 
Nahoru Odpovědět
2. srpna 9:20
Avatar
Jahnny
Člen
Avatar
Jahnny:4. srpna 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).

 
Nahoru Odpovědět
4. srpna 8:46
Avatar
Odpovídá na lukas.sei
Erik Šťastný:5. srpna 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.

Editováno 5. srpna 15:03
 
Nahoru Odpovědět
5. srpna 15:02
Avatar
Erik Šťastný:5. srpna 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

 
Nahoru Odpovědět
5. srpna 16:16
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
lukas.sei
Člen
Avatar
Odpovídá na Erik Šťastný
lukas.sei:5. srpna 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

 
Nahoru Odpovědět
5. srpna 22:34
Avatar
Odpovídá na lukas.sei
Erik Šťastný:6. srpna 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. :)

 
Nahoru Odpovědět
6. srpna 6:57
Avatar
lukas.sei
Člen
Avatar
Odpovídá na Erik Šťastný
lukas.sei:6. srpna 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)

 
Nahoru Odpovědět
6. srpna 9:45
Avatar
Odpovídá na lukas.sei
Erik Šťastný:6. srpna 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.

 
Nahoru Odpovědět
6. srpna 13:15
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Luboš Běhounek Satik:6. srpna 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.

Nahoru Odpovědět
6. srpna 13:47
https://www.facebook.com/peasantsandcastles/
Avatar
lukas.sei
Člen
Avatar
Odpovídá na Erik Šťastný
lukas.sei:6. srpna 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í.

 
Nahoru Odpovědět
6. srpna 21:19
Avatar
Odpovídá na lukas.sei
Erik Šťastný:6. srpna 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.

 
Nahoru Odpovědět
6. srpna 21:23
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 14 zpráv z 14.