errno() liefert E2BIG nach fehlgeschlagenem conncet()



  • Hallo Forum!
    Gleich bei einer ersten Post habe ich auch schon eine Frage:

    Ich habe eine einfache (noch sehr verbesserungswüridge) Klasse geschrieben, die es mir ermöglichen soll, eine Verbindung mit einem anderen Rechner herzustellen.

    connect() schlägt jedoch Fehl und errno liefert dann folgendes Ergebnis:

    E2BIG (Argument list too long (7))

    Hier die Headerdatei

    #ifndef _CLCONNECTION_H_
    #define _CLCONNECTION_H_
    
    #include <errno.h>
    
    #ifndef _INET_
    #define _INET_
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <sys/fcntl.h>
    #include <arpa/inet.h>
    #endif
    
    #ifndef _IOSTREAM_
    #define _IOSTREAM_
    #include <iostream>
    #endif
    
    class server_connection
    {
    	public:
    		server_connection(std::string host, unsigned int port);
    		~server_connection();
    
    		int establish_connection(void);
    		int establish_connection(std::string host, unsigned int port = 0);
    		unsigned int send_data(std::string string);
    		char* receive_data(void);
    
    	private:
    		int socket_id;
    		struct sockaddr_in dest_addr;
    
    		unsigned int m_port;
    		std::string m_host;
    };
    
    #endif
    

    Hier der dazu passende Codeteil

    #include "clconnection.h"
    
    server_connection::server_connection(std::string host, unsigned int port)
    {
    	m_host = host;
    	m_port = port;
    }
    
    server_connection::~server_connection()
    {
    	if(socket_id)
    		close(socket_id);
    }
    
    int server_connection::establish_connection(std::string host, unsigned int port)
    {
    	m_host = host;
    	if(port > 0)
    		m_port = port;
    
    	return establish_connection();
    }
    
    int server_connection::establish_connection(void)
    {
    	socket_id = socket(AF_INET, SOCK_STREAM, 0);
    	if(socket_id == -1)
    		return false;
    
    	// Change socket_id to a non-blocking socket
    	if (fcntl(socket_id, F_SETFL, O_NDELAY) == -1)
    		return false;
    
    	// DNS Resolve
    	struct hostent *host_ref;
    	host_ref = gethostbyname(m_host.c_str());
    	if(!host_ref)
    		return false;
    
    	printf("IP Address : %s\n", inet_ntoa(*((struct in_addr *)host_ref->h_addr)));
    
    	dest_addr.sin_family = AF_INET;
    	dest_addr.sin_port = htons(m_port);
    	dest_addr.sin_addr.s_addr = ((struct in_addr*)(host_ref->h_addr))->s_addr;
    	memset(&(dest_addr.sin_zero), '\0', 8);
    
    	if(-1 == connect(socket_id, (sockaddr*)&dest_addr, sizeof(sockaddr)))
    	{
    		return false;
    	}
    
    	return true;
    }
    
    unsigned int server_connection::send_data(std::string string)
    {
    	std::string send_string;
    	send_string = string + "\r\n";
    	return send(socket_id, send_string.c_str(), strlen(send_string.c_str()), 0); 
    }
    
    char* server_connection::receive_data(void)
    {
    	char buffer[10000];
    	recv(socket_id, buffer, strlen(buffer), 0);
    	return buffer; 
    }
    

    Bin für jeden Lösungsvorschlag dankbar!

    Gruß,

    subclasser



  • Bin für jeden Lösungsvorschlag dankbar!

    if(-1 == connect(socket_id, (sockaddr*)&dest_addr, sizeof(sockaddr)))
    

    ändern in

    if(-1 == connect(socket_id, (sockaddr*)&dest_addr, sizeof(dest_addr)))
    

    BTW fällt mir bei deiner Klasse noch auf:

    int establish_connection(std::string host, unsigned int port = 0);
    

    Glaubst du wirklich 0 ist ein guter Defaultwert für einen Port?

    server_connection::~server_connection()
    {
        if(socket_id)
            close(socket_id);
    }
    

    Das Socket wird nur geschlossen wenn socket_id != 0. Aber 0 könnte auch eine gültige socket_id sein.

    // Change socket_id to a non-blocking socket
    if (fcntl(socket_id, F_SETFL, O_NDELAY) == -1)
         return false;
    

    Damit überschreibst du eventuelle andere Flags des Deskriptors. Deswegen sollte der Code folgendermaßen aussehen. Und um POSIX Kompatibel zu sein solltest du statt O_NDELAY O_NONBLOCK nehmen:

    int flags;
    if (fcntl(socket_id, F_GETFL, &flags) == -1) return false;
    if (fcntl(socket_id, F_SETFL, flags | O_NONBLOCK) == -1) return false;
    
    char* server_connection::receive_data(void)
    {
        char buffer[10000];
        recv(socket_id, buffer, strlen(buffer), 0);
        return buffer; 
    }
    

    Der Array buffer existiert nachdem die Funktion ihren Dienst erfüllt hat nicht mehr. Du gibst also einen ungültigen Pointer zurück und wirst dafür höchstwarscheinlich SIGSEGV dafür kassieren, wenn strlen() das nicht schon vorher tut. Am Besten ist es du machst aus den Buffer eine Membervariable deiner Klasse.

    Und dann noch zu deiner Klasse generell: Beschäftige dich mal mit Exceptionhandling. Zuletzt noch ein gut gemeinter Tipp, such dir (oder lass dir eins Empfehlen) _gutes_, _intensives_ Tutorial für Sockets und Unixprogrammierung im Allgemeinen raus.

    mfg



  • Danke für deine Hilfe!

    Habe die Fehler beseitigt.

    Leider funktioniert das Verbinden immer noch nicht, errno() liefert noch immer E2BIG.

    Hat jemand eine Idee?


Anmelden zum Antworten