unerklärliches Verhalten??



  • Hi,
    Ich habe mir mal ein kleines Programm zusammengeschrieben, welches allerdings ein für mich unerklärliches verhalten hervorruft:

    int main(void)
    {
    	signal(SIGPIPE, pipe_error_handler); // redirect Pipe-errors to custom handler to prevent Program from termination (send() signals a broken pipe if peer is closed)	
    	Server = new TCPServer(4000, &error_handler ,&recv_handler); //Server is global
    	Server->startServer();
    	while(true)
    	{
    		string input;
    		cin >> input;
    		Server->sendMsg(input.c_str(),input.length());
    	}
    }
    

    die sendMsg-funktion:

    void TCPServer::sendMsg(const char *toSend, const int len) 
    	{
    		cout << "---" << endl;
    	}
    

    Als Ausgabe erhalte ich auf der Konsole immer eine konstante folge von 3 bindestriche pro zeile

    Ich weiß aber nich woran das liegt (da ja std::cin normalerweise blockierend ist)... ich hoffe es kann mir jemand von euch helfen

    MFG



  • versuchs mal mit std::cin.ignore(std::numeric_limitsstd::streamsize::max(), '\n'); innerhalb der while-schleife. std-header 'limits' einbinden nicht vergessen 😉

    warum erstellst du einen std::string, übergibst der memberfunktion dann aber doch nur den cstring? nen const std::string& zu übergeben spart dir nervige c_str()-aufrufe und den zweiten funktionsparameter 😉



  • vielleicht so schrieb:

    versuchs mal mit std::cin.ignore(std::numeric_limitsstd::streamsize::max(), '\n'); innerhalb der while-schleife.

    Leider keine Änderung. Es passiert genau das selbe wie vorher 😞



  • Ach ja, die funktion sendMsg() wird NUR in der Schleife aufgerufen, sonst nirgends.

    vielleicht so schrieb:

    warum erstellst du einen std::string, übergibst der memberfunktion dann aber doch nur den cstring?

    Weil nicht nur std::strings übergeben werden können sondern auch "rohe" daten



  • Da nicht bekannt ist, was in den Serverklassen noch so passiert, probier mal

    void sendMsg(const char *toSend, const int len)
    {
        cout << "---" << endl;
    }
    
    int main(int argc, char *argv[])
    {
        while(true)
        {
            string input;
            cin >> input;
            sendMsg(input.c_str(),input.length());
        } 
    
        return 0;
    }
    

    Denn das sollte ohne Schnickschnack scho funktionieren.
    Ansonsten sollte man mal den Debugger fragen.



  • Leider genau das selbe Ergebnis 😞
    Ich weiß schon wirklich nicht mehr woran das liegen kann
    In einem 2ten Programm funktioniert es genau wie es soll.



  • Vielleicht solltest du mal beim Compilierungsvorgang ALLES neu erstellen. (oder Debug-ordner löschen)
    Das wirkt oft Wunder, falls du es nicht schon probiert hast.

    Oder 😃 du sicherst dir deine .h und .cpp weg, löschst dein Projekt und erstellst es neu.

    Ansonsten wüsst ich auch nicht. 😞



  • Hab ich schon gemacht.
    Gibts einen Debug-Ordner bei g++??
    Wenn ich das ganze TCPServer Zeug auskommentier dann funktionierts.
    Aber ich weiß nicht warum es mit nicht funktioniert, da die Funktion wirklich nur an der einen stelle im ganzen Projekt aufgerufen wird



  • Erst hieß es doch:

    Unbekannt schrieb:

    Leider genau das selbe Ergebnis 😞
    Ich weiß schon wirklich nicht mehr woran das liegen kann
    In einem 2ten Programm funktioniert es genau wie es soll.

    😃 und nun heißt es also doch

    Unbekannt schrieb:

    Wenn ich das ganze TCPServer Zeug auskommentier dann funktionierts.

    Da hast du ja schonmal nen Anhaltspunkt. Aber wie die Klasse nun so
    Aussieht und was sie beinhaltet, weiß niemand 🕶



  • BasicMan01 schrieb:

    Aber wie die Klasse nun so
    Aussieht und was sie beinhaltet, weiß niemand 🕶

    Naja, ich weiß wie sie aussieht 😃
    aber ich weiß nicht ob es sinn macht jetzt die ganze klasse hier zu posten ...

    naja versuchen kann ichs ja mal:
    header:

    /*************
    Includes
    *************/
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <signal.h>
    #include <string>
    #include <cstring>
    #include <queue>
    
    #include <netdb.h> //for gethostbyname()
    
    #include <iostream>
    #include <errno.h>
    
    /************
    Class-Deklaration
    ************/
    
    /**************
    INFO:
    	this class uses error-codes in this way : 0xA***, where *** is the actual code;
    ***************/
    using namespace std;
    
    class TCPServer
    {
    	public:
    		TCPServer(short port,void (*errorfct)(const string, const int, const char), void (*functPtr)(const char *, const int));
    		~TCPServer();
    		bool startServer();
    		void closeServer();
    		void sendMsg(const char *toSend, const int len); //sends toSend buffer (if not everything could be sent the function tries to send the rest of the buffer)
    
    		void *readThread();	//should be private
    		void *writeThread();	//as above
    		void *doListen();	//as above
    
    	private:
    
    		void listenSock(void);
    
    		void (*readPtr)(const char *, const int);
    		void (*signal_error)(const string, const int, const char); //params: string = message, int = error-code, char = priority
    
    		int socket_fd, new_socket_fd;
    		struct sockaddr_in sin;
    
    		pthread_t readThreadid;
    		pthread_t writeThreadid;
    
    		pthread_mutex_t shutdownmutex;
    		bool shutdown;
    
    		struct dataWrapper
    		{
    			char data[1024];
    		};
    
    		pthread_mutex_t writebuffermutex;
    		queue <dataWrapper> writebuffer;
    
    		pthread_cond_t startSending;		
    
    };
    

    und die implementierung:

    #include "TCP_server.hpp"
    
    	static void *_readThread(void *This);	//prototypes for static functions
    	static void *_writeThread(void *This);
    	static void *_listenThread(void *This);
    
    	TCPServer::TCPServer(short port,void (*errorfct)(const string, const int ,const char ),void (*funct)(const char *, const int))
    	{
    		readPtr = funct;
    		signal_error = errorfct;
    		if(pthread_mutex_init(&shutdownmutex,NULL)!=0)
    		{
    			signal_error("could not initialize 'shutdownmutex'",0xA012,2);
    		}
    		if(pthread_mutex_init(&writebuffermutex,NULL)!=0)
    		{
    			signal_error("could not initialize 'writebuffermutex'",0xA013,2);
    		}
    		shutdown = false;
    		if(pthread_cond_init (&startSending,NULL)!=0)
    		{
    			signal_error("could not initialize 'startSending'-signal",0xA014,2);
    		}
    
    		sin.sin_family = AF_INET;		//set protocol family to Internet 
    		sin.sin_port = htons(port);		// set port no. 
    		sin.sin_addr.s_addr  = INADDR_ANY;	// set IP addr to any interface 
    
    		writeThreadid = 0;
    		readThreadid = 0;
    	}
    
    	TCPServer::~TCPServer()
    	{
    		closeServer();
    		pthread_mutex_destroy(&shutdownmutex);
    		pthread_mutex_destroy(&writebuffermutex);
    		pthread_cond_destroy(&startSending);
    	}
    
    	bool TCPServer::startServer()
    	{
    		if ( (socket_fd = socket(AF_INET, SOCK_STREAM, 0 ) ) < 0) { // create socket
    			signal_error("could not create socket",0xA001,1); // heavy error (retry startServer)
    			return false;
    		}
    		int opt = 1; 
      		if(setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0) { 
        			signal_error("execution of 'setsockopt' failed" ,0xA00F, 3);
      		}
    		//then bind it to my address and specified port num
    		if (bind(socket_fd, (struct sockaddr *)&sin, sizeof(sin) ) < 0 ){
    			signal_error("could not bind socket to port",0xA002,1); // heavy error
    			return false;
    		}
    		if (listen(socket_fd, 1)) 
    		{ 
        			signal_error("error while listening",0xA003,1); // listen error (heavy)
    		}
    		listenSock();
    		return true;		
    	}
    
    	void TCPServer::closeServer(void)
    	{
    		pthread_mutex_lock(&shutdownmutex);
    		shutdown = true;
    		pthread_mutex_unlock(&shutdownmutex);
    
    		pthread_cond_signal(&startSending); // tell the sending thread to shut down (if it is stuck waiting for signal)
    
    		if(pthread_kill(writeThreadid,0) == 0) //check if writeThread is still alive - if so kill it
    		{
    			signal_error("writeThread was not closed properly",0xA00A,3); //not fatal, but still an error
    			if(pthread_cancel(writeThreadid)!=0)
    			{
    				signal_error("writeThread could not be force-closed",0xA00B,3); //not fatal, but still an error
    			}
    		}
    		if(pthread_kill(readThreadid,0) == 0) //check if readThread is still alive - if so kill it
    		{
    			signal_error("readThread was not closed properly",0xA00C,3); //not fatal, but still an error
    			if(pthread_cancel(readThreadid)!=0)
    			{
    				signal_error("readThread could not be force-closed",0xA00D,3); //not fatal, but still an error
    			}
    		}
    
    		close(new_socket_fd);
    		close(socket_fd);
    	}
    
    	void TCPServer::sendMsg(const char *toSend, const int len) //Might be faster when signaling everytime the buffer is filled (at least if len is very big)
    	{
    
    		cout << "---" << endl;
    		/*if(writeThreadid > 0)
    		{
    			int packetBytes = 0;
    			do
    			{
    				dataWrapper myData;
    				memset(myData.data,0,sizeof(myData.data));
    				strncpy(myData.data,&toSend[packetBytes], len<=1024?len:1024 );
    				packetBytes += 1024;
    				pthread_mutex_lock(&writebuffermutex);   // lock write-buffer
    				writebuffer.push(myData);
    				pthread_mutex_unlock(&writebuffermutex); // unlock write-buffer
    			}
    			while(len > packetBytes);
    
    			pthread_cond_signal(&startSending); // tell the writing thread that the buffer has been filled
    		}
    		else
    		{
    			signal_error("Not connected to client",0xA011,4);
    		}*/
    	}
    
    	void TCPServer::listenSock(void)
    	{
    		pthread_t listenThread;
    		if(pthread_create(&listenThread,NULL,_listenThread,this))
    		{
    			signal_error("ERROR: could not create listenThread",0xA00E ,1); // almost fatal error (could be solved by retrying)
    		}
    	}
    
    	void *TCPServer::doListen()
    	{
    		if(writeThreadid > 0)
    		{
    			pthread_join(writeThreadid,NULL);
    		}
    		if(readThreadid > 0)
    		{
    			pthread_join(readThreadid,NULL);
    		}
    
    		writeThreadid = 0;
    		readThreadid = 0;
    
    		while(!writebuffer.empty()) //empty buffer
    		{
    			writebuffer.pop();
    		}
    
    		if (close(new_socket_fd) < 0) {
    			signal_error("error closing socket",0xA008,3); //not fatal, but still an error
    		}
    		unsigned int sinlen = sizeof(sin);
    		if ( (new_socket_fd = accept(socket_fd, (struct sockaddr *) &sin, &sinlen) ) < 0 )
    		{
      			signal_error("error accepting client",0xA004,2);  //medium error
    		}
    		pthread_mutex_lock(&shutdownmutex);	// lock variable "shutdown"
    		shutdown = false;			// prevent threads from closing immediately
    		pthread_mutex_unlock(&shutdownmutex);	// lock variable "shutdown"
    
    		if(pthread_create(&writeThreadid,NULL,_writeThread,this))
    		{
    			signal_error("could not create writeThread",0xA006,1);
    		}
    
    		if(pthread_create(&readThreadid,NULL,_readThread,this))
    		{
    			signal_error("could not create readThread",0xA005,1);
    		}
    
    		return 0; 
    	}
    
    	void *TCPServer::readThread(void)
    	{
    		pthread_mutex_lock(&shutdownmutex);
    		while(!shutdown)
    		{
    			pthread_mutex_unlock(&shutdownmutex);	// unlock variable "shutdown"
    			char msg[1024];
    			int status = recv(new_socket_fd, msg, sizeof(msg),0 ); // read message from client 
    
    			if(status <= 0) // client closed transmission or an error occured
    			{
    				if(status < 0) //error
    				{
    					signal_error("error receiving from client",0xA007,3);
         					//cout << strerror(errno) << endl;
    				}
    				else
    				{
    					signal_error("connection closed by client",0xA010,4);
    				}
    				//cout << "connection closed" << endl;
    				pthread_mutex_lock(&shutdownmutex);	// lock variable "shutdown"
    				shutdown = true;			// close threads properly
    				pthread_mutex_unlock(&shutdownmutex);	// lock variable "shutdown"
    			}
    			else
    			{
    				readPtr(msg,status);
    			}
    			pthread_mutex_lock(&shutdownmutex);	// lock variable "shutdown"
    		}
    		pthread_mutex_unlock(&shutdownmutex); // unlock variable "shutdown"
    
    		pthread_cond_signal(&startSending); // tell the other thread to shut down
    		listenSock(); //restart Threads
    		return 0;
    	}
    
    	void *TCPServer::writeThread(void)
    	{
    		pthread_mutex_lock(&shutdownmutex);
    		while(!shutdown)
    		{
    			pthread_mutex_unlock(&shutdownmutex);	// unlock variable "shutdown"
    
    			char toSend[1024];
    			char *pos = toSend;
    			int bytesSent = 0;
    
    			pthread_mutex_lock(&writebuffermutex);   // lock write-buffer
    			if(writebuffer.empty())
    			{
    				pthread_cond_wait(&startSending, &writebuffermutex); // wait for send() function to signal filled buffer
    			}
    			if(!writebuffer.empty()) // if writebuffer is still empty, it received the signal an should shut down
    			{
    				strncpy(toSend,writebuffer.front().data,1024);
    				writebuffer.pop();
    				pthread_mutex_unlock(&writebuffermutex); // unlock write-buffer
    
    				while(bytesSent < toSend+1024-pos ) //send all data
    				{
    					bytesSent = send(new_socket_fd, pos, toSend+1024-pos,0 );
    					if ( bytesSent < 0 ) {  
    			       			signal_error("error sending Data",0xA009,3);
    			       			bytesSent = 1024; //pretend to have sent all data to get out of loop
    			       			pthread_mutex_lock(&shutdownmutex);	// lock variable "shutdown"
    						shutdown = true;			// close threads properly
    						pthread_mutex_unlock(&shutdownmutex);	// lock variable "shutdown"
    					}
    				}
    			}
    			else
    			{
    				pthread_mutex_unlock(&writebuffermutex); // unlock write-buffer
    			}
    			pthread_mutex_lock(&shutdownmutex);	// lock variable "shutdown"
    		}
    		pthread_mutex_unlock(&shutdownmutex); // unlock variable "shutdown"
    		return 0;
    	}
    
    	static void *_readThread(void *This)
    	{
    		return ((TCPServer*)This)->readThread(); 
    	}
    
    	static void *_writeThread(void *This)
    	{
    		return ((TCPServer*)This)->writeThread(); 
    	}
    
    	static void *_listenThread(void *This)
    	{
    		return ((TCPServer*)This)->doListen();
    	}
    

    Falls jemand etwas findet bin ich sehr dankbar.
    natürlich sind auch hinweise auf etwaige andere Fehler wilkommen 😉

    LG



  • Ich vermute mal, dass das ganze jetzt wohl im Linux/Unix Forum besser aufgehoben ist.

    PS.: Ich weiß das mein Fehler-Handling nicht optimal und eher exotisch ist 😃
    aber wenn jemand einen besseren Vorschlag hat... immer her damit



  • Hat keiner eine Idee????

    Ich sitze jetzt schon seit stunden daran ohne irgendwas ungewöhnliches festzustellen, außer dem Grund für diesen Thread 😞

    Ich hoffe es kann sich doch noch jemand überwinden sich das anzusehen

    LG



  • Was machen pipe_error_handler, error_handler und recv_handler?



  • Das:

    void error_handler(string msg,int code, char priority)
    {
    	switch(priority)
    	{
    		case 0:
    		cout << "FATAL ERROR: "  << msg << " (" << hex << code << dec << ")" << endl << "TERMINATING!" << endl;
    		exit(-1);
    		break;
    		case 1:
    		cout << "HEAVY ERROR: "  << msg << " (" << hex << code << dec << ")" << endl << "restarting might be necessary" << endl;
    		break;
    		case 2:
    		cout << "MEDIUM ERROR: " << msg << " (" << hex << code << dec << ")" << endl;
    		break;
    		case 3:
    		cout << "MINOR ERROR: "  << msg << " (" << hex << code << dec << ")" << endl;
    		break;
    		case 4:
    		cout << "INFORMATION: "  << msg << " (" << hex << code << dec << ")" << endl;
    		break;
    	}
    }
    void recv_handler(const char *msg, int len)
    {
    	cout << "received: " << msg <<" (" << len << ")" << endl;
    }
    
    void  pipe_error_handler(int n)
    {
    	cout << "server received SIGPIPE" << endl;
    }
    


  • ENDLICH 😃 😃 😃 😃 😃 😃 😃

    Ich habs gefunden. Schuld waren folgende Zeilen in void *TCPServer::doListen(void) :

    if (close(new_socket_fd) < 0) 
    {
    	signal_error("error closing socket",0xA008,3); an error
    }
    

    Ich weiß nicht warum, aber es funktioniert.
    Falls jemand eine Erklärung dafür hat wäre ich dankbar, wenn nicht: auch egal, jetzt funktionierts ja 😃

    LG


Anmelden zum Antworten