meine Socket Library (Alpha Version)
-
Hallo Leute.
Letztens hat es mich geschockt, dass boost immer noch keine Sockets hat. Da habe ich mir gedacht, so schwer kann es doch nicht sein, eine Socketlibrary zu schreiben.
OK, es ist wesentlich schwerer als ich dachte
Aber dank realisticers und nmans Hilfe läuft die erste Version bereitsAn dieser Stelle großer Danke an die Beiden (vorallem an realisticer).
der Code ist noch mies und hat sicher noch ne Menge Bugs - ausserdem erzeugt er unter dem VC++ eine Menge Warnungen
Das wichtigste Designmerkmal ist, dass ein Socket ein Stream ist:
asl::basic_ServerSocket und asl::basic_ClientSocket und asl::basic_AcceptSocket
sind von basic_iostream abgeleitet.asl::Address repräsentiert die Zieladresse des Sockets.
Ein select ist noch nicht implementiert. Und accept() returned nur ein SocketInfo - daraus lässt sich ein basic_AcceptSocket erstellen. Man kann also bereits Sinnvoll damit arbeiten. Auch wenn noch sehr viel fehlt.
Nur seid ihr dran: was fehlt denn noch alles? Wo sind Fehler, was ist ungut gelöst? Bitte beachtet, dass dies die aller erste Version ist: ich habe es nur gerade für windows 'gehackt' - die Plattforumunabhängigkeit wird noch verbessert, denn da sind teilweise unschöne hacks drinnen.
Bitte postet eure Meinung und kritik.
-
Ich habe auf meiner Platte nen Wrapper für Linux Sockets, ist imho schön gelöst
und auch ziemlich einfach gehalten, da ich nicht den Autor kenne (steht auch nix
in den sources), würd ich es dir wenn du willst mailen, aber öffentlich hochladen
ist nicht drin, da ich wie gesagt keine Ahnung habe wer der Autor ist.
-
das wäre sehr nett: toni@schornboeck.net
-
thx für den Code.
Allerdings finde ich das dort nicht so elegant gelöst
-
ich hab mir den Code zwar noch nicht komplett angesehen, da ich etwas wenig Zeit hab. Aber mir ist folgendes aufgefallen: gethostbyadd und gethostbyname sind laut POSIX 1003.1-2001 obsolte. Schau dir mal man: getaddrinfo(3),man: getnameinfo(3),man: gai_strerror(3) an
-
ich hab mich auch mal an einem (kleinen) wrapper versucht.
der hat bei weitem nicht den funktionsumfang deiner lib;
und ich hab die sockets auch nicht als stream implementiert.was ich unschoen finde (ich hab mir den code nicht im detail
angesehen, nicht sauer sein, wenn ich was falsch interpretiere :)):
das initialisieren der sockets (wsastartup/-cleanup) wuerde (bzw. hab ich)
ich als singleton implementieren. der konstruktur macht startup;
der destruktor cleanup.wenn du willst schick ich dir den code auchmal ;).
-
entelechie schrieb:
was ich unschoen finde (ich hab mir den code nicht im detail
angesehen, nicht sauer sein, wenn ich was falsch interpretiere :)):
das initialisieren der sockets (wsastartup/-cleanup) wuerde (bzw. hab ich)
ich als singleton implementieren. der konstruktur macht startup;
der destruktor cleanup.Das WSAStartup habe ich nur brutal reingehackt, weil ich es unter linux entwickelt habe...
Da muss ich mir noch etwas schönes überlegen - das Problem ist ja, dass ich nicht weiss wie man das WSAStartup schön verstecken kann...
Wenn du da eine gute Idee hast... nur her damit.
-
so hatte ich das gemeint:
Socket::SocketLib* instance = 0; Socket::SocketLib::SocketLib() { initSocketLib(); } Socket::SocketLib::~SocketLib() { #ifdef _UNIX_ // nothing #else WSACleanup(); #endif } Socket::SocketLib* Socket::SocketLib::GetInstance() { static SocketLib socketLib; if ( instance == 0 ) instance = &socketLib; return instance; } void Socket::SocketLib::initSocketLib() throw( SocketException ) { #ifdef _UNIX_ // nothing #else /* * 0: not initialized * 1: initialized * -1: error: could not initialize socket lib (windows only) */ static char initState = 0; // Init: windows only if ( initState == 1 ) return; if ( initState == -1 ) throw SocketException( "initSocketLib initState -1" ); WSADATA wsa; if ( WSAStartup( MAKEWORD( 2, 2 ), &wsa ) == 0 ) initState = 1; else { initState = -1; throw SocketException( "initSocketLib WSAStartup != 0" ); } #endif }
und in den header dateien die socket funktionen brauchen
wird das getinstance aufgerufen:namespace
{
Socket::SocketLib* socketlib = Socket::SocketLib::GetInstance();
}vielleicht kannst du was damit anfangen.
-
entelechie schrieb:
so hatte ich das gemeint:
Socket::SocketLib* instance = 0; Socket::SocketLib::SocketLib() { initSocketLib(); } Socket::SocketLib::~SocketLib() { #ifdef _UNIX_ // nothing #else WSACleanup(); #endif } Socket::SocketLib* Socket::SocketLib::GetInstance() { static SocketLib socketLib; if ( instance == 0 ) instance = &socketLib; return instance; } void Socket::SocketLib::initSocketLib() throw( SocketException ) { #ifdef _UNIX_ // nothing #else /* * 0: not initialized * 1: initialized * -1: error: could not initialize socket lib (windows only) */ static char initState = 0; // Init: windows only if ( initState == 1 ) return; if ( initState == -1 ) throw SocketException( "initSocketLib initState -1" ); WSADATA wsa; if ( WSAStartup( MAKEWORD( 2, 2 ), &wsa ) == 0 ) initState = 1; else { initState = -1; throw SocketException( "initSocketLib WSAStartup != 0" ); } #endif }
und in den header dateien die socket funktionen brauchen
wird das getinstance aufgerufen:namespace
{
Socket::SocketLib* socketlib = Socket::SocketLib::GetInstance();
}vielleicht kannst du was damit anfangen.
Warum initSocketLib()? Du hast doch einen Konstruktor, warum dann noch ne
extra Memberfunktion dafuer?mfg
v R
-
@Shade
Hast du dir die Sandkasten-Versionen möglicher Boost-Socket-Libs angeschaut?
Z.B.
http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?BoostSocketUnd was spricht gegen die ACE-Wrapper? Platformübergreifender wird's wohl kaum
-
Naja, ich will nicht unbedingt in allen Klassen das Init aufrufen - das fände ich etwas doof. Und atexit() ist genauso gut wie der dtor eines singletons.
@Hume:
ja, angesehen schon. allerdings zielt boost ja nicht gerade darauf ab eine 'easy to use' library zu sein und mein wissen über sockets ist begrenztdh ich kann mit den texten dort nur relativ wenig anfangen - zumal die ja eine 'super duper mega geile' socket library planen. Mir reicht etwas einfaches
ACE fällt deshalb weg, weil ich mich damit noch nie näher beschäftigt habe. und ich eigentlich keine große Motivation verspüre neben boost noch eine weiter riesige Library zu verwenden. schon garnicht wenn ich nur einen kleinen teil daraus brauche. und soweit ich sehe, sind ACE Sockets keine streams, oder?
-
Naja, ich will nicht unbedingt in allen Klassen das Init aufrufen - das fände ich etwas doof. Und atexit() ist genauso gut wie der dtor eines singletons.
nein, das Problem ist, dass atexit nur eine bestimmte Anzahl an Funktionen verwalten können muss. Das sind zwar per Standard unter POSIX mindestens 32 Funktionen, was aber im Endeffekt doch nicht so viel sein kann und es ist bestimmt nicht so leicht rauszufinden, warum das Programm auf einmal nicht mehr so geht wie vorher nur weil irgend wie deine Library dazu gelinkt wurde, vorallem da sich der Fehler ja auf die Komplette Anwendung verteilen kann
HumeSikkins schrieb:
Und was spricht gegen die ACE-Wrapper? Platformübergreifender wird's wohl kaum
ACE ist doch ein riesiger Brocken, vorallem durch die CORBA Funktionen?
Hab mich aber noch nicht so intensiv mit ACE befasst.
-
Von Volkard kam mal folgender Trick für den WSA-Kram, damit man nichtmehr explizit Init() aufrufen braucht:
struct SocketInit { SocketInit() { WSAInit... }; ~SocketInit() { WSAClean... }; }; class Socket { Socket() { static SocketInit sinit; // so hat man den Init-Kram beim ersten Anlegen eines Sockets // und aufgeräumt wird am Ende des Programms } };
Und ich finde diese #ifdefs im Code immer schlimm. Würde da um die entsprechenden Teile lieber nochmal Wrapper-Funktionen und -typedefs rumbauen und diese in extra Dateien auslagern.
-
kingruedi schrieb:
ACE ist doch ein riesiger Brocken, vorallem durch die CORBA Funktionen?
Die CORBA-Funktionen gehören zu TAO (The ACE ORB) und damit strenggenommen nicht teil der eigentlichen ACE-Lib. Ich meinte allerdings auch nur die ACE-Socket-Wrapper. Das ist nicht so viel. Sind sehr patternlastig. Dafür aber gut dokumentiert.
und soweit ich sehe, sind ACE Sockets keine streams, oder?
Es gibt zwar eine ACE_SOCKET_Stream-Klasse, aber die ist kein Stream im iostream-Sinne.
-
DrGreenthumb schrieb:
Von Volkard kam mal folgender Trick für den WSA-Kram, damit man nichtmehr explizit Init() aufrufen braucht:
Mein Problem ist aber: ich habe viele verschiedene Klassen in denen Socket-Funktionen sind. Momentan sind es zwar nur Socket und Address, aber da kommen ja noch mehr dazu
Und ich finde diese #ifdefs im Code immer schlimm. Würde da um die entsprechenden Teile lieber nochmal Wrapper-Funktionen und -typedefs rumbauen und diese in extra Dateien auslagern.
ich hab lieber #ifdefs im code als code doppelt. Aber ich hab es in der aktuellen version schöner getrennt als in der verlinkten html Datei. Da ist dann alles auch auf mehrere Dateien verteilt.
@Hume:
und genau das (keine streams) ist n KO Kriterium für mich.Es ist ja weniger dass ich die Socketlib wirklich brauche, es ist eher so, dass ich das als anlass nahm zu sehen ob es wirklich so schwer ist streams zu implementieren wie einige Leute in letzter Zeit im c++ Forum behauptet haben.
Und ich muss sagen, dank Josuttis STL Buch, ist es nicht wirklich schwer.
btw: so wie ich es sehe (hab mir ACE mal kurz angeschaut), geht bei ACE die Code-Schönheit aufgrund der absoluten portierbarkeit flöten, oder? Zumindest finde ich den Code nicht wirklich ansprechend (was ich so in den Tutorials gesehen habe).
Und für mich gibt es eh nur Windows und Linux - andere OS habe ich nicht, lohnt sich also nicht dafür zu programmieren
-
@shade:
keine der klassen soll das init aufrufen.
du schreibts die deklaration in eine .cpp datei
(oder - falls eine statische methode bereits auf die
socket api zugreift - in die .h datei), damit ist
sichergestellt, dass die sockets initialisiert sind..h namespace { SocketLib* x = SocketLib::GetInstance(); } class Socket { ... }
-
du könntest dir mal die socket-funktionen von Qt angucken:
http://doc.trolltech.com/3.2/qsocket.htmldie sind sehr gut aufgebaut und einfach zu bedienen.
und wenn du dabei bist guck dir auch QSocketDevice, QHostAddress, QSocketNotifier und Input/Output and Networking an
da wirst du bestimmt so einige anregungen finden.
edit: http://doc.trolltech.com/3.2/clientserver-example.html da, ein anwendungsbeispiel.
-
ich finde die CSocket aus der MVC gut, event. kannst du dich ja daran orientieren