Sockets -> accept (die 1000.)
-
Hallo!
Ich hab mich mal dem Tutorial auf www.c-worker.ch gewidmet und das Winsock Programm nach programmiert. Ich hab aber paar Klassen verwendet und auch cout anstatt von printf aber das ist nicht relevant...
Mein Problem liegt, wie so oft, bei accept()!
Zuerst wird eben Winsock gestartet, dann ein Socket erstellt, ein Port (in meinem Fall 237) gebunden und dann geht der Server in den listen modus..
dann sollte ja accept aufgerufen werden!
Mein Problem ist: Sobald ich accept aufrufe, wird NICHTS angezeigt! Das verstehe ich nicht!
Der Code von c-worker.ch funktioniert aber, ich hab den 1:1 per copy&paste in ein Projekt kopiert und da funktioniert es..
Ich mach es gleich, nur eben mit Klassen aber es klappt überhaupt nicht!
hier mal mein Code
int main (void) { cServer myserver; long res; char buffer[255]; res = myserver.Server_startup(); if (res != 0) cout << "Server meldet: Winsock nicht gestartet!\n"; else cout << "Server meldet: Winsock erfolgreich gestartet!\n"; res = myserver.Server_createSock(); if (res != INVALID_SOCKET) cout << "Server meldet: Socket erfolgreich erstellt!\n"; else cout << "Server meldet: Socket nicht erstellt!\n"; res = myserver.Server_bind("237"); if (res != SOCKET_ERROR) cout << "Server meldet: Socket wurde an Port 237 erfolgreich gebunden!\n"; else cout << "Server meldet: Socket wurde nicht gebunden!\n"; res = myserver.Server_listen(); if (res != SOCKET_ERROR) cout << "Server meldet: Neuer Status: Server im Listen Modus...\n"; else cout << "Server meldet: Server nicht im Listen Modus!\n"; res = myserver.Server_accept(); if (res != INVALID_SOCKET) cout << "Server meldet: Neue Verbindung akzeptiert!\n"; else cout << "Server meldet: Neue Verbindung nicht akzeptiert!\n"; while(res != SOCKET_ERROR) { res = recv(myserver.getConSocket(), buffer, strlen(buffer), 0); if (res == 0) { cout << "Server hat die Verbindung getrennt.. \n"; break; } if (res == SOCKET_ERROR) { cout << "Fehler: Receive"; break; } buffer[res] = '\0'; cout << "Nachricht: " << buffer; } return(0); }
Kommentiere ich die accept Geschichte aus, wird alles bis listen angezeigt, und alles klappt auch! aber sobald es dabei ist steht in der Konsole nur ein blinkendes "_" und sonst nichts..
Hier die Klasse:
class cServer { public: inline cServer () {} inline ~cServer () { WSACleanup(); closesocket(this->acceptsocket); closesocket(this->connectedsocket); } inline SOCKET getConSocket (void) { return this->connectedsocket; } int Server_startup (void); int Server_createSock (void); int Server_bind (string port); int Server_listen (void); int Server_accept (void); private: WSADATA wsadata; SOCKET acceptsocket; SOCKET connectedsocket; SOCKADDR_IN addr; }; int cServer::Server_startup (void) { return WSAStartup(MAKEWORD(2,0), &this->wsadata); } int cServer::Server_createSock (void) { this->acceptsocket = socket(AF_INET, SOCK_STREAM, 0); return this->acceptsocket; } int cServer::Server_bind(string port) { memset(&this->addr, 0, sizeof(SOCKADDR_IN)); this->addr.sin_family = AF_INET; this->addr.sin_port = htons(atoi(port.c_str())); this->addr.sin_addr.s_addr = INADDR_ANY; return bind(this->acceptsocket, (SOCKADDR*)&this->addr, sizeof(SOCKADDR_IN)); } int cServer::Server_listen (void) { return listen(this->acceptsocket, 10); } int cServer::Server_accept (void) { this->connectedsocket = accept(this->acceptsocket, NULL, NULL); return this->connectedsocket; }
ok is viel Code, sorry aber ich bin echt schon am verzweifeln..
Kann mir irgendjemand helfen?! Wär super
Vielen Dank im Vorraus
mfg
sTr33n
-
Bin mir nicht ganz sicher weil ich lange nichts mehr mit der Net - API gemacht habe, aber ich denke die Function "... accept(...);" blockiert
solange bis
der Client eine Nachricht zum Server schickt!
Der Socket der zurückgegeben wird müsste dann nehmlich wieder bei der
"... recv(...);" Function verwendet werden um in eine Messagepuffer einzulesen
(ein deklarier. char - Array)!
Man kann doch davon ausgehen das Du gleichzeitig mit nen fertigen Client testest?Was mir auch noch auffällt,
Deine Portnummer liegt in einen Bereich der
von komerzieller netzwerkfähiger Software genutzt werden kann. Ich benutzte
bei selbstgeschriebenen Code immer Portnummern >= 5000! Dann komm sich auch nichts ins gehegen. Den die Portnummer ist wie eine "Hausnummer jeder Netzapplikation"ich hoffe es war hilfreich,
mfg sclearscreen
-
Hast Du ne Dokumentation zur WINDOWS-API zur Hand dann such mal unter "accept"!
Dann fällt Dir was bei Deiner Implementierung auf!!!
int cServer::Server_accept (void) { this->connectedsocket = accept(this->acceptsocket, NULL, NULL); return this->connectedsocket; }
Der 2. Parameter bei Accept muss auf Deine
SOCKADDR_IN addr;
zeigen die Function "accept" brauch aber nen Zeiger auf ne SOCKADDR also bei Übergabe noch casten, etwa so
(SOCKADDR*) &addr
!
Der 3. Parameter muss die Grösse der bzw. Deiner SOCKADDR_IN sein
d.h bei Übergabe dieses Parameter einfachsizeof(addr)
das ist das was mir beim 2.mal auffiel schau aber bitte noch mal selbst
in die WINDOWS - API Dokumentation in punkto "accept" Funktion dann siehst Du genau was ich damit meineich hoffe hab mich nicht vertippt als schau auch selbst nochmal nach
mfgsclearscreen
-
der 2. und 3. Parameter sind bei "accept" laut Doku optional wenn man se nicht braucht dann is be beiden "NULL" zu verwenden!
möchte man se verwenden
kann man in eine StrukturSOCKADDR_IN addrClient;
anlegen und "accept" legt dort Daten vom Client ab (etwa zu verwenden für ne
Logfile).
mir fällt also momentan doch nichts mehr auf also nimm doch vielleicht
mal ne grössere PORTNUMMer vielleicht liegts ja daran!mfg sclearscreen
-
Bei mir kommen folgende Meldungen des Programm!!!
**
Server meldet: Winsock erfolgreich gestartet!
Server meldet: Socket erfolgreich erstellt!
Server meldet: Socket wurde an Port 237 erfolgreich gebunden!
Server meldet: Neuer Status: Server im Listen Modus...
**Jetzt blockiert das Programm genau bei der Schleife also bei "... recv(...)"
das muss auch so sein denn dort kommt es erst wieder raus wenn ein Client
connected und was sendet! mit nen entsprechenden Client hab ich aber nisch getestet das müsste man aber unbedingt noch tun sonst weiss man wirklich nicht
obs wirklich geht.
Also ich denke so sollte es auch funzen, ich hab den CODE mit Kopieren
und einfuegen bei mir dann kompiliert und es funzt ohne das ich was verändert habe der CODE scheint vollkommen in Ordnung! Nun das hätte ich gleich mal tun sollen! Wenns bei Dir immer noch nicht geht könnts auch an deinen Compiler liegen und seinen Headerfiles die dieser mitbringt! Ich hab mehrere Compiler bei mir.
Zum Beispiel kann ich bei mir mit dem C++ 4.52 von Borland keine Netzwerkapplikationen schreiben, weil dort irgendwas mit den#include <windows.h>
bzw.
#include <winsock.h>
nicht stimmt!
also der Code funzt so dennoch die Portnummer würde ich auf jedenfall
ändern. Im Netz gibts irgendwo ne Page wo steht welche Portnummern von
welchen kommerziellen ernsten Programmen die auch vertrieben werden
genutzt werden! dann kann man seine Portnummer so wählen das nichts schief geht!ich hau mich jetzt erstmal aufs Ohr also soweit ist der Code erstmal In Ordnung
bei mir funzt es hab ohnen was zu ändern mit dem C++ 5.0 von Borland gecheckt!!!!!!!
mfg sclearscreen
-
Du wirst erstaunnt sein aber Dein CODE funzt ich hab nischt dran gemacht,
beherzige das mit der Portnummer aber trotzdem!Hier mein Code des TCP-Clienten dann kannste weiter testen!
der Code ist von den Adressen so angepasst das er mit deinen
CODE funzt, Du kannst Ihn so kopieren wie er ist.
127.0.0.1 ist localhost wenn du Client und Server direkt deinen
Rechner laufen lässt:#include <winsock.h> #include <stdio.h> //Prototypen int startWinsock(void); int main() { long rc; SOCKET s; SOCKADDR_IN addr; char buf[256]; // Winsock starten rc=startWinsock(); if(rc!=0) { printf("Fehler: startWinsock, fehler code: %d\n",rc); return 1; } else { printf("Winsock gestartet!\n"); } // Socket erstellen s=socket(AF_INET,SOCK_STREAM,0); if(s==INVALID_SOCKET) { printf("Fehler: Der Socket konnte nicht erstellt werden, fehler code: %d\n",WSAGetLastError()); return 1; } else { printf("Socket erstellt!\n"); } // Verbinden memset(&addr,0,sizeof(SOCKADDR_IN)); // zuerst alles auf 0 setzten addr.sin_family=AF_INET; addr.sin_port=htons(237); // wir verwenden mal port 12345 addr.sin_addr.s_addr=inet_addr("127.0.0.1"); // zielrechner ist unser eigener rc=connect(s,(SOCKADDR*)&addr,sizeof(SOCKADDR)); if(rc==SOCKET_ERROR) { printf("Fehler: connect gescheitert, fehler code: %d\n",WSAGetLastError()); return 1; } else { printf("Verbunden mit 127.0.0.1..\n"); } // Daten austauschen while(rc!=SOCKET_ERROR) { printf("\nZeichenfolge eingeben [max 256]: "); gets(buf); send(s,buf,strlen(buf),0); rc=recv(s,buf,256,0); if(rc==0) { printf("Server hat die Verbindung getrennt..\n"); break; } if(rc==SOCKET_ERROR) { printf("Fehler: recv, fehler code: %d\n",WSAGetLastError()); break; } buf[rc]='\0'; printf("\nServer antwortet: %s\n",buf); } closesocket(s); WSACleanup(); getchar(); return 0; } int startWinsock(void) { WSADATA wsa; return WSAStartup(MAKEWORD(2,0),&wsa); }
Viel Spass damit
jetzt aber ins Bett
mfg
-
Hallo!
Erstmal Danke für die recht schnelle Antwort!!!
Alsooo..
Port hab ich jetzt geändert, danke für den Tipp
Das wusste ich nämlich garnet..
Nun..
Ich verwende VC++ 6.0 Standard für die Kompilierung des Tutorials UND meines Codes. Das heisst daran kann es nicht liegen, da beide den selben Code verwenden.
Im Tutorial wird accept() genau so verwendet wie ich es tue.. ich weiss nicht warum das nicht klappt
Ich werd aber mal da ne Struktur angeben und das mal probieren.
Vielen Dank!!!
PS: Ich hatte mein Passwort verschmissen +g+
mfg
sTr33n
-
Ich hab jetzt mal die Funktion accept() abgeändert, aber jetzt stürzt das Programm ab..
Hier der Code
int cServer::Server_accept (void) { this->connectedsocket = accept(this->acceptsocket, (SOCKADDR*)&this->addr, (int*)sizeof(SOCKADDR)); return this->connectedsocket; }
Aber du sagst, bei dir bleibt er erst nachher hängen? Wie geht das ? bei mir klappt es nicht so!
Ich müsste erst einen Clienten verbinden, aber beim Tutorial und bei DIR mit meinem Code klappts? das kann ja nicht sein.. was kann da falschsein?!
mfg
-
Bei "... accept(... , (SOCKADDR*) &addr, ...);" also hier
int cServer::Server_accept (void) { this->connectedsocket = accept(this->acceptsocket, (SOCKADDR*)&this->addr, (int*)sizeof(SOCKADDR)); return this->connectedsocket; }
überschreibst Du mit Sicherheit "Die Daten an den Du Deinen Serverapplikation gebunden hast"
! Verwende diesen Parameter nur mit einer
zweitenSOCKADDR_IN clientDaten;
Struktur, den Accept legt dort
Daten von einen Clienten ab der connecten will(Zu verwenden wen Du eine Logfile zum registrieren von eingehenden Clients verwenden willst)! Du überschreibst dort nehmlich
Die Daten deiner laufenden Serverapplikation -> deswegen kommt sicherlich der
Absturz!!!!mfg
-
wegen flascher Verwendung von "SOCKADDR_IN addr;"
Deklarieren in deinen Serverobjekt Klasse wie auch immer
noch eine Struktur vom Typ "SOCKADDR_IN clientDaten;"
und aendere:int cServer::Server_accept (void) { this->connectedsocket = accept(this->acceptsocket, (SOCKADDR*)&this->addr, (int*)sizeof(SOCKADDR)); return this->connectedsocket; }
ietwa so ab damit Du die Serverdaten nicht ueberschreibst:
int cServer::Server_accept (void) { this->connectedsocket = accept(this->acceptsocket, (SOCKADDR*)&this->clientDaten, (int*)sizeof(SOCKADDR)); return this->connectedsocket; }
Dann sollte es nicht mehr Abstürzen!
Kommt jetzt ein connectendere Client stehen dort (bei "clientDaten")Verbindungsdaten vom Clienten
mfg
-
Hab folgende Deiner Implementierung folgendermaßen nochmal geandert und dann hat der Server
bei mir wieder gefunztint cServer::Server_accept (void) { int addrSize = sizeof(SOCKADDR); this->connectedsocket = accept(this->acceptsocket, (SOCKADDR*) &clientDaten, (int*) &addrSize); return this->connectedsocket; }
Sorry und mfg
-
Der bzw Dein TCP-Server (Fehler bei accept behoben) und mit 2. SOCKADDR_IN - Struktur:
#include <windows.h> #include <iostream.h> #include <cstring.h> class cServer { public: inline cServer () {} inline ~cServer () { WSACleanup(); closesocket(this->acceptsocket); closesocket(this->connectedsocket); } inline SOCKET getConSocket (void) { return this->connectedsocket; } int Server_startup (void); int Server_createSock (void); int Server_bind (string port); int Server_listen (void); int Server_accept (void); private: WSADATA wsadata; SOCKET acceptsocket; SOCKET connectedsocket; SOCKADDR_IN addr, clientDaten; }; int cServer::Server_startup (void) { return WSAStartup(MAKEWORD(2,0), &this->wsadata); } int cServer::Server_createSock (void) { this->acceptsocket = socket(AF_INET, SOCK_STREAM, 0); return this->acceptsocket; } int cServer::Server_bind(string port) { memset(&this->addr, 0, sizeof(SOCKADDR_IN)); this->addr.sin_family = AF_INET; this->addr.sin_port = htons(atoi(port.c_str())); this->addr.sin_addr.s_addr = INADDR_ANY; return bind(this->acceptsocket, (SOCKADDR*)&this->addr, sizeof(SOCKADDR_IN)); } int cServer::Server_listen (void) { return listen(this->acceptsocket, 10); } int cServer::Server_accept (void) { int addrSize = sizeof(SOCKADDR); this->connectedsocket = accept(this->acceptsocket, (SOCKADDR*) &clientDaten, (int*) &addrSize); return this->connectedsocket; } //////////////////////////////////////////////////////////////////// int main (void) { cServer myserver; long res; char buffer[255]; res = myserver.Server_startup(); if (res != 0) cout << "Server meldet: Winsock nicht gestartet!\n"; else cout << "Server meldet: Winsock erfolgreich gestartet!\n"; res = myserver.Server_createSock(); if (res != INVALID_SOCKET) cout << "Server meldet: Socket erfolgreich erstellt!\n"; else cout << "Server meldet: Socket nicht erstellt!\n"; res = myserver.Server_bind("237"); if (res != SOCKET_ERROR) cout << "Server meldet: Socket wurde an Port 237 erfolgreich gebunden!\n"; else cout << "Server meldet: Socket wurde nicht gebunden!\n"; res = myserver.Server_listen(); if (res != SOCKET_ERROR) cout << "Server meldet: Neuer Status: Server im Listen Modus...\n"; else cout << "Server meldet: Server nicht im Listen Modus!\n"; res = myserver.Server_accept(); if (res != INVALID_SOCKET) cout << "Server meldet: Neue Verbindung akzeptiert!\n"; else cout << "Server meldet: Neue Verbindung nicht akzeptiert!\n"; while(res != SOCKET_ERROR) { res = recv(myserver.getConSocket(), buffer, strlen(buffer), 0); if (res == 0) { cout << "Server hat die Verbindung getrennt.. \n"; break; } if (res == SOCKET_ERROR) { cout << "Fehler: Receive"; break; } buffer[res] = '\0'; cout << "Nachricht: " << buffer; } return(0); }
Und jetzt nochmal der TCP - Client zum testen:
#include <winsock.h> #include <stdio.h> //Prototypen int startWinsock(void); int main() { long rc; SOCKET s; SOCKADDR_IN addr; char buf[256]; // Winsock starten rc=startWinsock(); if(rc!=0) { printf("Fehler: startWinsock, fehler code: %d\n",rc); return 1; } else { printf("Winsock gestartet!\n"); } // Socket erstellen s=socket(AF_INET,SOCK_STREAM,0); if(s==INVALID_SOCKET) { printf("Fehler: Der Socket konnte nicht erstellt werden, fehler code: %d\n",WSAGetLastError()); return 1; } else { printf("Socket erstellt!\n"); } // Verbinden memset(&addr,0,sizeof(SOCKADDR_IN)); // zuerst alles auf 0 setzten addr.sin_family=AF_INET; addr.sin_port=htons(237); // wir verwenden mal port 12345 addr.sin_addr.s_addr=inet_addr("127.0.0.1"); // zielrechner ist unser eigener rc=connect(s,(SOCKADDR*)&addr,sizeof(SOCKADDR)); if(rc==SOCKET_ERROR) { printf("Fehler: connect gescheitert, fehler code: %d\n",WSAGetLastError()); return 1; } else { printf("Verbunden mit 127.0.0.1..\n"); } // Daten austauschen while(rc!=SOCKET_ERROR) { printf("\nZeichenfolge eingeben [max 256]: "); gets(buf); send(s,buf,strlen(buf),0); rc=recv(s,buf,256,0); if(rc==0) { printf("Server hat die Verbindung getrennt..\n"); break; } if(rc==SOCKET_ERROR) { printf("Fehler: recv, fehler code: %d\n",WSAGetLastError()); break; } buf[rc]='\0'; printf("\nServer antwortet: %s\n",buf); } closesocket(s); WSACleanup(); getchar(); return 0; } int startWinsock(void) { WSADATA wsa; return WSAStartup(MAKEWORD(2,0),&wsa); }
so funzt es bei mir, Verbindung und Nachrichtübermittlung bei dem Server klappt!
:pwenns immer noch nisch geht?
kann es sein das du rein zufällig ne bzw. die winsock2.h
includiert hast die damit gehts bei mir nisch ich verwende deshalb "winsock.h"mfg
-
Hallo!
Danke für deine Mühe
Ich hab gerade ein neues Projekt gemacht und das ganze HAAR GENAU EXAKTESTENS gleich abgeschrieben und siehe da: Es klappt net!
Das kann nicht sein! Das geht nicht..
Ich werd jetzt nochmal den neuen Code von dir probieren und hoffen dass es klappt!
Vielen Dank dass du dir die Mühe gemacht hast!!!!
mfg
-
is aus versehen geschehen aber diese Header includiert ihrer selbst
die "winsock.h" gleich mit!
Du kannst das aendern dann wird die EXE nen bisschen kleiner!
-
Hallo!
Wie erwartet, funktioniert es nicht
Der Server bleibt sofort hängen bei accept wieder mal..
naja ich weiss langsam echt nicht was da los is... am Code kanns einfach nicht liegen, weil das der selbe ist!
Trotzdem danke!!!
mfg
-
Ich habs ja bei mir mit C++ 5.0 von Boland getestet -> Ergebnis es geht anstandslos
Dann hab ichs mit Microsoft Visual C++ 6.0 getestet -> Ergebnis es geht nischt,
neben Headerfiles die er nicht findet "cstring.h" ganz zu schweigenIch nutze persöhnlich Microsoft Visual C++ aber sowieso nicht mehr
das ist etwas Nutzerunfreundlich meines erachtens!
Das soll aber keine Abwertung von Microsoft sein, nischts ist vollkommen!mfg
-
Du das kann nicht sein, dass MEIN Code nicht funktioniert aber der Code des Tutorials funktioniert..
beides ist mit VC kompiliert/gelinkt wurden!!
Der eine Code (aus dem Tutorial per c&p) funktioniert aber mein Code, der die selben Funktionen benutzt nur in einer klasse funktioniert nicht!
Erklär mir das mal
Das geht nicht!
-
Und zwar mit dem CBuilder 5.0 von Borland
und Dein Code mit der Klassenkapselung der Netzwerkfunktionen funktioniert
einwandfrei bezogen auf meinen Client und Dein Servercode!Nur VC 6.0 macht dicke Backen das is Compilerspezifisch und hat nichts unbedingt damit zu tun das der Code grundlegend falsch is!!!!!
Solche Probleme hatte ich schon des öfteren deswegen habe ich bei mir zu Hause
auch eineiges an Compilern und IDE's rumkullern! C/C++ - Compiler ist nicht
gleich C/C++ Compiler bezogen auf CODEtechnische Standards! So is nunmal das
Leben. Ich hab da schon so manches erlebt was ausser dieser Geschicht dort
funktioniert hat und auf ner anderen IDE nicht! Es gibt sogar Unterschiede
zwischen den verschiedenen Versionen von einer IDE von ein und demselben
Hersteller!!!Sumasomarum hab ich jez auf 3 verschiedenen Compilern getestet bei den
beiden Borlands klappts, und bei Visual C++ 6.0 gehts nisch! Ergo Compilerproblem!mfg
-
Ich hab jetzt den Code ausm Tutorial 1:1 übernommen und schritt für schritt in Klasse umgesetzt..
einziger Unterschied: ich benutze printf() und kein cout
Vielleicht liegts daran.. egal, es funktioniert und das ist das wichtigste +gg+
Vielen Dank jedenfalls für deine Hilfe!!!
mfg