Sockets in Thread ansprechen
-
Hallo,
ich bin ziemlich neu hier im Forum und hoffe, dass mir hier jemand aus der patsche Helfen kann

Und zwar schreibe ich momenatn an einer kleinen Serverapplikation. Dazu reserviert mir das Programm einen Port und wartet dann auf Clients die sich verbinden.
Wenn sich ein Client anmeldet wird ein ServerSocket-Objekt erzeugt, eine Struktur mit zusaetzlich ner Nummer gespeichert und ein Thread erzeugt, dem die Struktur dann als Argument uebergeben wird.
Wenn ich den Server starte und mich z.B. per telnet verbinden will knallt es aber dann, ich kann nicht mal Daten senden!
Das Ganze sieht in etwa so aus:
Im Hauptprogramm:#include "communication.h" #include "serversocket.h" #include "socketexception.h" #include <string> #include <iostream> #include <pthread.h> struct cl_str { unsigned int client_num; ServerSocket *new_sock; }; void* client_messages( void* ); int main ( int argc, char **argv ) { unsigned int client_num = 0; std::cout << "running....\n"; try { // Create the socket ServerSocket server( PORT ); while ( true ) { ServerSocket new_sock; server.accept( new_sock ); client_num++; cl_str structure; structure.client_num = client_num; structure.new_sock = &new_sock; pthread_t client_thread; pthread_create( &client_thread, NULL, client_messages, &structure ); // pthread_join( client_thread, NULL ); } } catch ( SocketException& e ) { std::cout << "Exception caught:" << e.description() << std::endl << "Exiting." << std::endl; } return 0; } void* client_messages( void *client_struct ) { cl_str *cl = ((cl_str*)(client_struct)); unsigned int num = (*cl).client_num; ServerSocket *new_sock = (*cl).new_sock; try { while ( true ) { std::string data; (*new_sock) >> data; std::cout << "client " << num << ": " << data << std::endl; } } catch ( SocketException& se ) { std::cout << "Exception getting client message!" << std::endl << se.description() << std::endl; } return 0; }Zustaendig fuer das Senden/Empfangen der Daten ist die Klasse Socket, hier ein Auszug:
int Socket::recv ( std::string& s ) const { char buf [ MAXRECV + 1 ]; s = ""; memset ( buf, 0, MAXRECV + 1 ); int status = ::recv ( m_sock, buf, MAXRECV, 0 ); if ( status == -1 ) { std::cout << "STATUS == -1 ERRNO == " << errno << " in Socket::recv\n"; return 0; } else if ( status == 0 ) { return 0; } else { s = buf; return status; } }Wenn ich in der Schleife im Hauptprogramm auf den Thread warte dann funktioniert alles einwandfrei, ich kann aber nicht mehrere Clients akzeptieren, und darum geht es mir!
Kann mir da jemand einen Tipp geben was ich falsch mache? Sitz seit ca. 2 Stunden und bin am experimentieren, finde aber keine Loesung
mfg
-
Ok, auf die Ursache bin ich gekommen. Anscheinend wird der Destruktor von Socket aufgerufen und zerstoert das Objekt bevor es ueberhaupt in den Thread gelangen kann - aber wieso?
-
moe szyslak schrieb:
aber wieso?
Wieso nicht?
server ist eine lokale Variable innerhalb des try-Blocks. Wenn das Programm diesen Block verlässt, wird server wie alle anderen lokalen Variablen auch zerstört.
-
server ist nicht betroffen vom destruktor sondern new_sock, und das Programm bleibt auch immer in der while-Schleife, das heisst es verlaesst sie nicht, trotzdem wird new_sock zerstoert.
-
moe szyslak schrieb:
server ist nicht betroffen vom destruktor sondern new_sock,
Und new_sock ist eine lokale Variable im Schleifenkörper, und wird daher nach jedem Schleifendurchlauf zerstört. Gleiches Prinzip.
-
MFK schrieb:
moe szyslak schrieb:
server ist nicht betroffen vom destruktor sondern new_sock,
Und new_sock ist eine lokale Variable im Schleifenkörper, und wird daher nach jedem Schleifendurchlauf zerstört. Gleiches Prinzip.
Ist klar, jetzt klappts auch, und zwar sieht das jetzt so aus:
#include "communication.h" #include "clientlist.h"; #include "serversocket.h" #include "socketexception.h" #include <string> #include <iostream> #include <pthread.h> struct cl_str { unsigned int client_num; ServerSocket *new_sock; }; void* client_messages( void* ); int main ( int argc, char **argv ) { unsigned int client_num = 0; Clientlist clients; ServerSocket *new_sock; std::cout << "running....\n"; try { // Create the socket ServerSocket server( PORT ); pthread_t client_thread; while ( true ) { new_sock = new ServerSocket(); server.accept( *new_sock ); // ServerSocket new_sock; // server.accept( new_sock ); client_num++; clients.add_client( *new_sock, "client mac", "client name" ); cl_str structure; structure.client_num = client_num; structure.new_sock = new_sock; pthread_create( &client_thread, NULL, client_messages, &structure ); } pthread_join( client_thread, NULL ); } catch ( SocketException& e ) { std::cout << "Exception was caught:" << e.description() << std::endl << "Exiting." << std::endl; } return 0; } void* client_messages( void *client_struct ) { cl_str *cl = ((cl_str*)(client_struct)); unsigned int num = (*cl).client_num; ServerSocket *new_sock = (*cl).new_sock; try { while ( true ) { std::string data; (*new_sock) >> data; std::cout << "client " << num << ": " << data << std::endl; } } catch ( SocketException& se ) { std::cout << "Exception getting client message!" << std::endl << se.description() << std::endl; } return 0; }Eigentlich sollte man das ja selber wissen, aber nachdem man 3 Jahre lang fast ausschliesslich mit Java arbeitet wird man halt doch wein wenig denkfaul

Danke!!!
-
Das ist immer noch nicht sicher, weil du immer noch die Adresse einer lokalen Variablen übergibst. Im Prinzip übergibst du immer wieder dieselbe Adresse. Da diese Variable keine Daten enthält, die Destruktoren haben, wird das meistens gutgehen. Aber wenn sich zwei Clients in kurzer Zeit verbinden, kann es passieren, dass beide Threads die Informationen des zweiten Clients auslesen. Entweder bringst du da eine Synchronisierung rein, oder du legst die Struktur auf dem Heap an.
-
Mit in den Heap legen, meinst du dabei so was [1]
Was wuerdest du sagen ist aus Performencegruenden besser? Hab die Moeglichkeit mit dem Heap noch nie benutzt!
-
Nein, meint er nicht. Er mein "free store".
-
moe szyslak schrieb:
Mit in den Heap legen, meinst du dabei so was [1]
Was wuerdest du sagen ist aus Performencegruenden besser? Hab die Moeglichkeit mit dem Heap noch nie benutzt!"Premature optimization is the root of all evil."
mit heap meint er das hier:
int* ptr = new int; // ... delete ptr;ansonsten würde ich mir bei c++ erstmal keine gedanken um performance machen. (das sage ich nicht nur, weil du vorher in java programmiert hast)