Ostatnimi czasy z nudów wziąłem się wreszcie za naukę socketów w C++. Miałem to już zrobić na początku maja, mam nawet wydrukowane samouczki, jednak myślę, że to właśnie one mnie do tego zniechęcały. A to nie był← pisane pod kątem C++, a to były zbyt obszerne i za dużo w nich było teorii. Dopiero kolejne poszukiwania (bodajże przedwczorajsze) naprowadziły mnie na właściwy trop. I tak oto, aby poznać sockety w praktyce, postanowiłem napisać sobie pseudokomunikator – Dandys IM. 😉
Póki co ma on tylko funkcję serwera (klienta mi się dopisać nie chciało, dlatego robi z niego teraz Telnet) i parę błędów (m.in. taki, że wiadomości pojawiają się czasem dopiero po wysłaniu wiadomości przez nas), ale mi to wystarczyło, żeby się przekonać, jak to fajnie, gdy mój pierwszy program z socketami potrafi porozumiewać się ze światem. 🙂
Niżej zamieszczam źródełko programu, jak komuś się chce, to wiadomo, co robić (nie wiadomo? no to: g++ socket_server.cpp -o socket_server). Jakby komuś się aż tak nudziło i poprawił buga, o którym pisałem, to proszę o kontakt.
I na koniec podziękowania dla testerów, których to często nękałem ostatnio:
- Eriz
- szlomo
Dzięki chłopaki za czas!
- Przykład prostego klienta oraz serwera z użyciem socketów
- Opis najczęściej używanych funkcji w programowaniu socketów (potrzebne do zrozumienia kodu z poprzedniego dokumentu)
jedna, maleńka uwaga – co tam robi goto? (tak mnie to zbulwersowało, że aż mi się nie chce przeglądać kodu dalej)
A jaką widzisz inną możliwość wyjścia z for? Tak, próbowałem break, ale on widocznie przerywał tylko jeden cykl tej pętli.
Haha, jeszcze trochę i będziesz jak Gorion 😉
powiem tak: normalnie?
warunek pętli nie musi być pojedynczy, and na warunek z licznikiem i !koniec powinno rozwiązać problem
lub, jeśli to ograniczenie 1000 znaków jest jakieś sztuczne – po prostu while do momentu równości znaku z ‘\0’
i jeszcze: po co funkcja policz? wykorzystujesz ją raz, a robi dokładnie to samo, co strlen? może się mylę, jeśli tak, to przepraszam
Pewnie, że można, ale goto też jest po to, żeby go używać, nieprawdaż? 🙂
Tablica znaków bufor ma 1000 elementów i dlatego funkcja policz bierze pod uwagę wszystkie jego elementy.
Wytłumaczenie jest proste: strlen siedzi w string.h, a po co include’ować cały nagłówek, skoro można sobie wyskrobać prostą, kilkulinijkową funkcję? Wiem, że nie warto wyważać otwartych drzwi, ale nie jest to znowu jakaś strasznie złożona funkcja, żeby trzeba przez nią było zawalać program całą dodatkową biblioteką.
nie, goto jest po to, żeby było wyklęte :> programowanie strukturalne rządzi się swoimi zasadami i nieużywanie goto jest jedną z nich
Ja z tego drugiego obozu jestem. 😉 Rozumiem, gdyby tam była masa goto, ale jedno goto w tym przypadku dodaje przejrzystości, tym bardziej, że nie przenosi gdzieś daleko, że trzeba przewijać, żeby zobaczyć, do czego odwołuje się goto.
ale warunek z końcem nie jest jakiś super nieczytelny, a trzyma się zasad
To już kwestia stylu pisania. Dla mnie takie jedno małe goto nie jest zbrodnią i jest bardziej czytelne, niż alternatywa warunków w pętli. Ważne, że program zgodny ze standardem C++. 🙂
i tu byśmy się nie zgodzili :> ale jeśli goto to tylko kwestia stylu, to ja sobie idę: o gustach się nie dyskutuje
Kwestia gustu i zastosowania, wiadomo, że nie wszędzie jest to pożądane. Ale zobacz, co piszą o tym np. Grębosz, Stroustrup – obydwaj są zgodni, że aby nie komplikować, czasem można zastosować goto. Poza tym, programy z pętlami zawierającymi koniunkcję lub alternatywę warunków trudno się potem debuguje.
Czekaj, przypadkowo mam Grębosza pod ręką, Tom 1 Symfonii, strona 26, sama góra: „Powiedzmy jasno, używanie instrukcji goto zdradza, że jest się złym programistą. To dlatego, że instrukcji tej zawsze da się uniknąć. Program (nad-) używający instrukcji goto jest dla programisty nieczytelny, a z kolei dla kompilatora stanowi to przeszkodzę w eleganckim skompliwaniu”.
Jest jeden przykład, kiedy goto się przydaje – ale przydaje, a nie, że jest polecane – wielokrotnie zagnieżdżone pętle.
I jeszcze raz wspomina o goto – wspominając, że jest to cecha kodu typu spaghetti, czyli stylu programowania liniowego. Uwagę o tym, co oznacza, że programujesz w sposób liniowy postaram sobie przemilczeć.
Ciekawa jestem, co o tej kwestii wspominał Stroustrup, bo aktualnie jego pod ręką nie mam.
Chcesz pisać w C++ – programowanie obiektowe, a sięgasz do technik sprzed dwóch generacji, nawet nie do programowania obiektowego.
Aha, nie chcę, żebyś pomyślał, że moim celem jest zdołowanie Ciebie jako programisty, nie mam takiego zamiaru, po prostu chciałam zwrócić uwagę na błąd, który rzucił mi się w oczy. Dziwni mnie co prawda opór przy bronieniu tego błędu i upieraniu się, że to wcale nie jest błąd, ale to już temat na inną dyskusję. Pozdrawiam i pisz więcej – wtedy się styl wyrabia 🙂
No tak, genialne. Tylko, że metody programowania to kwestia programisty i nie ma tutaj tych „jedynie słusznych”. Tak, programowanie obiektowe, liniowe – skoro goto jest tak haniebne dla piszącego, to dlaczego nie zabrania go standard C++, albo chociaż GCC nie wywala warningów? Poza tym Grębosz pisze, że break powinno zatrzymywać także pętlę for, dlatego też początkowo było tak właśnie break zamiast goto. Dopiero debugowanie wykazało, że – co ciekawe – break przerywa tylko jeden cykl tej pętli.
Nie lubię jedynie słusznych metod programowania, bo każdy myśli inaczej i każdy zawiera to inaczej w kodzie. Doskonale widać to po aplikacjach open source, w których kodzie panuje niespotykany nigdzie burdel (nikt tego nie standardyzuje). Może i użycie w tym wypadku goto świadczy o mnie źle, jednak dla mnie jest to czytelne i – co najważniejsze – takie coś po prostu łatwiej się debuguje, bo wiem, kiedy pętla została przeskoczona, a nie zastanawiam się, dlaczego tym razem akurat się zakończyła.
Poza tym – chyba masz naprawdę zły humor dzisiaj, bo piszesz w takim stylu, jakbyś chciała mnie na siłę zaszczuć swoim myśleniem. Otworzyłaś larum o jedna, poboczną funkcję policz. Mam tylko nadzieję, że wynika to – jak pisałem wcześniej – z tego, że „wstałaś dzisiaj lewą nogą”, a nie z faktu, że chcesz sobie na siłę udowodnić, jakie to Twoje myślenie jest słuszne.
Pozdrawiam i życzę poprawienia humoru, bo mi trochę radość z opanowania podstaw socketów przez Ciebie ucichła.
OK, dzięki. Ale goto jest przecież pełnoprawną instrukcją C++, więc została do niego włączona tylko po to, żeby jej użycie było uważane za błąd? Poza tym, jak mówisz (a i ja sam się na tym podparłem), jest to opinia konkretnego człowieka. Tak samo, jak ja nie lubię pisania w ten sposób:
while {
…
}
tak samo ktoś może uważać, że mieszanie stylów, czy np. używanie wstawek jest błędne. Dla mnie jedynym wyznacznikiem jest (najpierw) standard C++, potem wygoda.
goto to dinozaur, który dawno temu powinien zostać usunięty ze specyfikacji języka, a książka Grębosza nie jest żadnym autorytetem w dziedzinie C/C++.
Popatrz, a nie został.
Nie został, bo wisi na nim brzemię kompatybilności wstecz. Jak myślisz, dlaczego w nowoczesnych językach takich jak Java czy Python nie znajdziesz goto?
Nie mam pojęcia o tych językach, więc nie mogę odpowiedzieć na to pytanie. Ale czyż nie dzięki tej kompatybilności wstecz nie trzeba portować starych aplikacji do kolejnej wersji języka?
Tak – o to właśnie chodzi. Jeżeli ktoś kiedyś popełnił wielki błąd i użył instrukcji goto, zostało mu to wybaczone. Ale nie oznacza to, aby w dalszym ciągu powielać złe nawyki.
Ja nie uważam, żeby używanie GOTO było złe. Pod warunkiem, że się programuje w BASICu na C64.
to teraz pobaw sie libxml i przepisz to na jabbera 😛
W założeniu miałem naukę socketów na jakimś praktycznym przykładzie, a nie używanie bibliotek. 🙂
Dandys – jak się dobrze już naumiesz wszystkiego, pobaw się w przeportowanie Skulltaga na linuksa 😛
Genialny tekst, muszę zapamiętać 😉
A wiecie, że w PHP6 chcą wprowadzić instrukcję goto? Jedyna nadzieja, że bogowie ich ukarzą za ten postępek (tak, jestem, z tego samego obozu co Weronika). Na uczelni mnie karali nawet za break, co było dopiero nonsensem („bo to nie jest programowanie strukturalne!” – zagrzmiał profesor – „a kto używać break, continue, albo goto będzie, ten w piekle skończy, a tam będzie płacz i zgrzytanie zębów”).
No to teraz Dandysowi stoi droga otwarta przed nowym jabberd, a nie tam portowanie Skulltaga 😉
Ktos – od tego jest smoku, a Skulltag pod linuksem by mogl byc, bo to jedyna gra, dla ktorej mysle nad instalacja windy 😛
Ciekawe. To jak używaliście takich instrukcji, jak np. switch?
W początkowym okresie uczyliśmy się Pascala, gdzie instrukcja
case
jest inaczej rozwiązana. Potem (następny semestr) przy nauce C break już jest, np. przy tymswitch
, niezbędne. Poza tym jednak nie używamy w ogóle, polegając nawhile
zamiastfor
w wielu wypadkach (zwłaszcza przy wszelkiego rodzaju przeszukiwaniach tablic).Zastanawia mnie jak radzi sobie obecny pierwszy rok mając C i Pascala na tym samym semestrze 😉
A tak BTW, to gdzie studiujesz?
Politechnika Lubelska w Lublinie (taka jest pełna nazwa, zawsze mnie śmieszy – tak jakby lubelska mogła być gdzieś poza Lublinem), informatyka na wydziale Informatyki i Elektrotechniki.
Jest jeszcze trzech joggerówców z tej uczelni i kierunku 😉
O popatrz, akurat tam się wybieram. 😀 (o ile będą mnie chcieli z tą moją maturą) W którym roku maturę zdawałeś?
Poprawność kodu != stosowanie całej składni języka. Pisząc dla siebie, droga wolna, robisz tak aby przeglądając źródła miesiąc później wszystko było czytelnie i zrozumiałe. Spróbuj jednak wysłać taki kod aplikując o pracę programisty a zapewniam, że zostanie on oceniony niżej niż praca kogoś potrafiącego obejść stosowanie przestarzałych instrukcji.
Przepraszam, ze się przywalę, ale te sockety to w C są – czyste C. 😛 Reszta to tak, C++, agreed.
Dandys, co do goto: dlaczego np. w poprawnym „ideologicznie” XHTML-u nie użyłbyś <center>? 😛
eRIZ: Jeszcze gdybym znał XHTML-a, a ja ledwo mam pojęcie o trochę bardziej skomplikowanych rzeczach w HTML-u. 🙂
[quote]Dopiero debugowanie wykazało, że – co ciekawe – break przerywa tylko jeden cykl tej pętli.[/quote]
Może zanim zaczniesz programować w C++, to jednak zapoznaj się z C (czyt: przeczytaj K&R’a, bo tam wyraźnie stoii (K&Rv2 rozdział 3 punkt 7 „Break and Continue”: „A break causes the innermost enclosing loop or switch to be exited immediately”.))
Zgadzam się z Weroniką, Deelym i innymi, goto w C++ nie powinno mieć prawa bytu. Akceptuję jedynie w szczególnych przypadkach i tylko w kodzie pisanym w C.