 |
www.elektronik.si Forum o elektrotehniki in računalništvu
|
Poglej prejšnjo temo :: Poglej naslednjo temo |
Avtor |
Sporočilo |
Djurodrljaca Član

Pridružen-a: Pet 19 Dec 2003 16:31 Prispevkov: 393 Aktiv.: 1.66 Kraj: Mengeš
|
Objavljeno: Pon Jun 19, 2006 10:24 pm Naslov sporočila: |
|
|
Kaj vrne funkcija niti nisem gledal, ker sem sever samo predelal iz neke delujoče rešitve. Bom pa še malo predelal program po tvojih priporočilih. Prej niti nisem vedel, če funkcija pošlje vrednost 0x00, ampak glede na to da nikjer ne piše da je ne pošlje jo verjetno bo poslal.
Sedaj pa mislim, da je večino napak že odkritih, tako da bojo verjetno kmalu odpravljene. Če odkriješ še kaj, nimam nič proti temu da mi poveš.
Bom po teh popravkih tudi objavil gor server in client aplikacijo. Ta client pa je bil narejen predvsem za testiranje serverja, ker je tapravi client GSM naprava.
|
|
Nazaj na vrh |
|
 |
Djurodrljaca Član

Pridružen-a: Pet 19 Dec 2003 16:31 Prispevkov: 393 Aktiv.: 1.66 Kraj: Mengeš
|
Objavljeno: Tor Jun 20, 2006 9:18 am Naslov sporočila: |
|
|
Sem popravil nekatere napake. Namesto strlen sem uporabil strnlen, dodal sem pošiljanje terminacijskega znaka ('\0') ter malo bolj opazno naredil izračun dolžine podatkov (prej je bil strlen v funkciji send sedaj pa je pred funkcijo in v funkcijo vpišem samo število bajtov za poslat).
Kot sem obljubil prilagam server.cpp in client.cpp. Sta pa ta programa narejena za UDP protokol.
Opis: |
|
 Download |
Ime datoteke: |
Server.cpp |
Velikost datoteke: |
5.26 KB |
Downloadano: |
11 krat |
Opis: |
|
 Download |
Ime datoteke: |
Client.cpp |
Velikost datoteke: |
3.84 KB |
Downloadano: |
0 krat |
|
|
Nazaj na vrh |
|
 |
Sokrat Član


Pridružen-a: Čet 25 Avg 2005 11:00 Prispevkov: 5584 Aktiv.: 23.52
|
Objavljeno: Tor Jun 20, 2006 10:55 am Naslov sporočila: |
|
|
Hm, v server.cpp vidim nekaj reci, ki so ocitno posledica tvoje predelave obstojecega primera in integracije tvojih dodatkov, bolj specificno: opazam, da je originalna koda ze delovala pravilno (je ze vrnila kolicino prejetih podatkov), ti si pa po nepotrebnem kompliciral z str*len(). Vrednost je v spremenljivki nRet in mora znasati tocno stevilo sprejetih bajtov (= vrednost, ki jo isces in za katero po nepotrebnem klices dodatno funkcijo), ne glede na terminacijo (ob uporabi terminacije bo seveda en znak vec, saj posljes tudi terminator sam). Koda ze prej preveri ali je prislo do napake, tako da je ta aspekt pokrit.
Prav tako ni potrebno prebrskati celotnega bufferja za tvoj magic number ("#"), ampak je dovolj iskanje do nRet - 1, ce je nRet > 0 (kar mora biti, sicer skoci koda ze zgoraj ven iz glavne zanke). Zdaj tudi razumem zakaj si napisal, da se v bufferju "pojavljajo eni nakljucni znaki" - to se zgodi zato, ker je tudi omenjeno iskanje po celotnem bufferju tvoja napaka; ce bi preiskal samo dejansko prejete podatke, do tezave seveda ne bi prislo.
Nekoliko nizje vrstica
szBuf[nRet]=0;
sluzi temu, da ni potrebno posiljati terminacijskega znaka za znakovni niz (\0), prej pa ti ni pomagala ravno zaradi tvojega buga, omenjenega v prejsnjem odstavku (jaz sem zadnjic predpostavil, da je program sicer napisan pravilno). To dodajanje 0x00 po sprejemu prihrani prenos enega bajta - ce gre za veliko kolicino malih paketkov, je lahko prihranek kar opazen, zato je tovrstno pocetje bolj smiselno kot posiljanje terminatorja, dokler se zavedas omejitev (ne smes postali vec kot N - 1 znakov, kjer je N dolzina bufferja).
V glavnem ... cel kup nepotrebnega kompliciranja in tezav, ki jih lahko elegantno odpravis, pa se koda bo bolj ucinkovita. Vrzi ven tisto traparijo z dolzino stringa, namesto buflen podaj nRet (kar je vrednost, ki jo isces), preverjaj samo vsebuno bufferja od 0 do nRet - 1 (pri tvoji obliki pogoja zamenjaj i z nRet) in dodaj nekaksen error/exception handling za takrat, ko pride do nepredvidenega primera.
Cisto zares ti bo pomagalo, ce si izposodis prej omenjeno knjigo in preberes vsaj osnovna poglavja - ce bi to naredil takoj, ne bi sploh vpeljeval toliko problemov v svoj izdelek
|
|
Nazaj na vrh |
|
 |
Djurodrljaca Član

Pridružen-a: Pet 19 Dec 2003 16:31 Prispevkov: 393 Aktiv.: 1.66 Kraj: Mengeš
|
Objavljeno: Tor Jun 20, 2006 11:41 am Naslov sporočila: |
|
|
Zgleda da moram še malo opisati moj protokol pošiljanja podatkov (bi ga verjetno moral opisati že prej, da ne bi prihajalo do podobnih nesporazumov).
Naprava se najprej pošlje na server podatke v obliki: "<tekst>#<checksum>"
Potem server ta podatek pregleda, da vidi, če je tekst pravilne oblike ("<tekst>#<checksum>") in če se <checksum> ujema z izračunanim. Glede na prejšen rezultat pošlje nazaj v napravo tekst "\r\nOK\r\n" oz. "\r\nERROR\r\n".
Še na kratko: server prejme podatek, ga preveri in pošlje potrditev.
Trenutno naprava še ne pošilja terminacijskega znaka, zato je potreben tisti szBuf[nRet]=0; (tudi ko bo, verjetno ne bi bilo slabo to obdržati, saj tako zagotoviš da je v vsakem primeru na koncu terminacija).
|
|
Nazaj na vrh |
|
 |
Sokrat Član


Pridružen-a: Čet 25 Avg 2005 11:00 Prispevkov: 5584 Aktiv.: 23.52
|
Objavljeno: Tor Jun 20, 2006 12:35 pm Naslov sporočila: |
|
|
Terminacija ne bo potreba, ce popravis kodo tako, kot sem napisal zgoraj (uporabljaj nRet, ki ga vrne recvfrom()).
Vse, kar sem napisal v oprejsnjem sporocilu, drzi tudi zdaj, ko si opisal format poslanih podatkov - ne brskaj po celem bufferju, pa ne bo nobenih tezav, ki bi jih bilo potrebno odpravljati z dodatnim flikanjem lukenj.
|
|
Nazaj na vrh |
|
 |
Djurodrljaca Član

Pridružen-a: Pet 19 Dec 2003 16:31 Prispevkov: 393 Aktiv.: 1.66 Kraj: Mengeš
|
Objavljeno: Tor Jun 20, 2006 12:58 pm Naslov sporočila: |
|
|
Verjetno z brskanjem misliš na ta for stavek:
Koda: |
for(i=0; i<255; i++)
{
if(szBuf[i]==0) //// če v stringu ni bilo znaka '#' zavrni sprejet podatek
{
k=0;
chksum=1;
break;
}//end if
if(szBuf[i]=='#')
{
k=3;
break;
}//end if
chksum += szBuf[i];
}//end for |
Prvi if preveri, če se pred znakom '#' pojavi '\0'. To pomeni da je oblika prejetega podatka napačna, ker ne vsebuje znaka '#', ki loči podatke od checksuma.
Drugi if pa poskrbi, da se izračuna checksum za podatke do znaka '#'. Če se je for zanka zaključila, ko je prišla do znaka '#', potem se še prebere vrednost, ki je za tem znakom in ta vrednost je checksum. Ko imam oba checksuma ju primerjam in na podlagi tega potem pošljem potrditev.
V sami kodi ne vidim več nobenega buga in tudi ne flikanja lukenj.
|
|
Nazaj na vrh |
|
 |
Sokrat Član


Pridružen-a: Čet 25 Avg 2005 11:00 Prispevkov: 5584 Aktiv.: 23.52
|
Objavljeno: Tor Jun 20, 2006 2:18 pm Naslov sporočila: |
|
|
Kot sem ti ze prej napisal, je napaka v tem, da preverjas vsebino celotnega bufferja, ne glede na to, koliko znakov si dejansko sprejel. Sprejel si nRet znakov, zato je potrebno preveriti le pozicije od 0 do nRet - 1.
Tvoja koda spodaj pod prvo vrstico citiranega dela (iskanje terminacijskega znaka) je samo posledica omenjene napake - ce luknje ne bi bilo, je ne bi bilo potrebno dodatno popravljati, zato je boljse, da napako odpravis, kot pa da "zdravis" simptom. Ce ne vidis tezave v tem izseku, potem bos imel bistveno vecje probleme, ko bos prisel do obseznejse kode, ki ne bo tako lahko odpuscala malomarnosti (glej M$ Windows).
|
|
Nazaj na vrh |
|
 |
Djurodrljaca Član

Pridružen-a: Pet 19 Dec 2003 16:31 Prispevkov: 393 Aktiv.: 1.66 Kraj: Mengeš
|
Objavljeno: Tor Jun 20, 2006 2:32 pm Naslov sporočila: |
|
|
No to pa sem spregledal (i<255 v for zanki) in bom popravil, ampak jaz moram pregledati buffer, ker edino tako izvem, če string vsebije '#' in ko ga najde gre ven iz for zanke, če pa namesto znaka '#' najde '\0' potem ugotovi, da je string napačne oblike in gre tudi ven iz for zanke. Tako da "it's not a bug, it's a feature".
|
|
Nazaj na vrh |
|
 |
Sokrat Član


Pridružen-a: Čet 25 Avg 2005 11:00 Prispevkov: 5584 Aktiv.: 23.52
|
Objavljeno: Tor Jun 20, 2006 2:50 pm Naslov sporočila: |
|
|
Znaka \0 ne bos nasel, ce ga prej tja sam ne postavis, postavis pa ga na mesto nRet v bufferju (torej dolzian + 1). Ce bi pregledal samo nRet znakov (namesto 255), ne bi \0 nikoli nasel, ce je nikoli ne posljes in ce ne pride do napak pri prenosu. V tem primeru niti ni potrebno postavljati terminacijskega znaka, saj ne sluzi nicemur vec.
To, da bi rad nasel "#", mi je jasno, zato sem tudi ze prej ustrezno oblikoval moje odgovore - ce naredis tako, kot sem napisal ze nekaj sporocil nazaj, bo delalo ravno tako, kot ti to pricakujes, ne bo pa nobenih bugov in neucinkovitosti v izvedbi.
|
|
Nazaj na vrh |
|
 |
Djurodrljaca Član

Pridružen-a: Pet 19 Dec 2003 16:31 Prispevkov: 393 Aktiv.: 1.66 Kraj: Mengeš
|
Objavljeno: Tor Jun 20, 2006 3:07 pm Naslov sporočila: |
|
|
V for zanki je sedaj že 255 popravljen v nRet.
\0 pa je potreben, ker ko grem iz for zanke dobim lokacijo prve cifre checksuma, ki je za '#' in to potem pretvorim v int s funkcijo atoi ( rcvchksum=atoi(&szBuf[i+1]); )
Se ti pa še enkrat zahvaljujem za vso pomoč pri odkrivanju napak.
|
|
Nazaj na vrh |
|
 |
Djurodrljaca Član

Pridružen-a: Pet 19 Dec 2003 16:31 Prispevkov: 393 Aktiv.: 1.66 Kraj: Mengeš
|
Objavljeno: Sre Jun 21, 2006 9:35 am Naslov sporočila: |
|
|
Sokrat, mogoče veš zakaj funcija recvfrom() neha delati, ko v for zanki uporabim nRet? (nRet je int, zato sem tudi i spremenil iz char v int)
Funkcija se takoj vrne z nekim errorjem in to samo takrat, ko dam v for zanko nRet, ko pa to spremenim nazaj v 255 pa spet dela.
(Server sedaj že 9,5 ur dela brez problem s tem da vsako minuto pošljem en telegram iz naprave na server.)
|
|
Nazaj na vrh |
|
 |
Sokrat Član


Pridružen-a: Čet 25 Avg 2005 11:00 Prispevkov: 5584 Aktiv.: 23.52
|
Objavljeno: Sre Jun 21, 2006 10:51 am Naslov sporočila: |
|
|
Ni mi najbolj jasno kaj ti ne deluje - uporabi debugger in spremljaj stanje spremenljivk ter tok programa, da vidis kje pride do napake oz. do nepravilnega poteka.
Ce si samo spremenil
for(i=0; i<255; i++)
v
for(i = 0; i =< nRet; i++)
potem ne vidim razloga zakaj ne bi delovalo.
Za primerjavo bi sploh lahko uporabil funkcijo iz knjiznice (npr. memcmp() ali katero od funkcij za iskanje po stringih, katerih je kar nekaj), namesto teh komplikacij.
|
|
Nazaj na vrh |
|
 |
Djurodrljaca Član

Pridružen-a: Pet 19 Dec 2003 16:31 Prispevkov: 393 Aktiv.: 1.66 Kraj: Mengeš
|
Objavljeno: Sre Jun 21, 2006 11:22 am Naslov sporočila: |
|
|
Problem je bil v tem, da sem na začetku programa uporabljal listenSocket, potem pa je bil nekje pred recvfrom() deklariran SOCKET remoteSocket in sem potem uporabljal remoteSocket in ne listenSocket. Sedaj ko sem to popravil pa dela tudi z nRet v for zanki. Še ena napaka zaradi predelave različnih verzij serverja ter seveda površnosti.
Zelo čudno mi je pa to, da mi je server sploh delal na ta način.
|
|
Nazaj na vrh |
|
 |
|
|
Ne, ne moreš dodajati novih tem v tem forumu Ne, ne moreš odgovarjati na teme v tem forumu Ne, ne moreš urejati svojih prispevkov v tem forumu Ne, ne moreš brisati svojih prispevkov v tem forumu Ne ne moreš glasovati v anketi v tem forumu Ne, ne moreš pripeti datotek v tem forumu Ne, ne moreš povleči datotek v tem forumu
|
Uptime: 6 dni
Powered by phpBB © 2001, 2005 phpBB Group
|