client IP auslesen



  • Hi,

    ich schreibe momentan zwei kleine Programme, eine Client Anwendung und eine Server Anwendung. Bisher tut mein Programm folgendes:
    - Server Anwendung öffnet einen Socket und hört ihn ab.
    - Client Anwendung verbindet sich und übermittelt Kommandos.
    - Server handelt je nach Kommando

    Nun öffnet der Client selbst einen Socket und soll einen Datenstrom vom Server empfangen. Um sich mit dem Client verbinden zu können, braucht der Server natürlich die IP. Diese hat er ja durch die bestehende Verbindung bereits.
    Meine Frage: wie lese ich diese aus?
    Angehängt, der relevante Teil meiner Server Anwendung. Aus diesen Informationen will ich die Client Adresse auslesen.

    Um Fragen vorweg zu nehmen, warum ich noch eine Verbindung aufbaue wo doch bereits eine bidirketionale Verbindung besteht... Es soll eine reine "Kommando" Verbindung und eine reine Daten-Verbindung geben

    int main(int argc, char *argv[])
    {
    	pthread_t data;		//define thread for data transmission
    	int sockfd, newsockfd;	//both are file descriptors for open sockets
    	int p=1; //p indicates if data transmission thread already in use (p=0)
    	int n;		//file descriptor for sockets
    	socklen_t clilen;	//Clientadresse length
    	char command[255];	//Buffer for client input
    
    	struct sockaddr_in serv_addr, cli_addr;	
    
    	sockfd = socket(AF_INET, SOCK_STREAM, 0);	
            //socket() creates endpoint, returns descriptor
            //AF_INET = IPv4
            //SOCK_STREAM = seq., rel., two-way, connection-based byte streams.
    	if (sockfd < 0)			
    	{	
    		error("ERROR opening socket");
    	}
    
    	bzero((char *) &serv_addr, sizeof(serv_addr)); 	
            //initialisiert serv_addr mit 0
    	serv_addr.sin_family = AF_INET;	        //use IPv4
    	serv_addr.sin_addr.s_addr = INADDR_ANY;	//IP-address of the host
    	serv_addr.sin_port = htons(2556);       //define portnumber
    
    	//bind() assigns the address specified by addr to the socket referred to     by the file descriptor sockfd.
    	//int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    	if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
    	{
                  error("ERROR on binding");
    	}
    
    	while (1)
    	{
    		bzero(command,255);		//initialisiere command buffer
    		listen(sockfd, 5);		
    //int listen(int socket, int backlog) - backlog, something with the queue
    		clilen = sizeof(cli_addr);	//Länge der client addresse
    		newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    
    		read(newsockfd,command,255);
    		if (n < 0) error("ERROR reading from socket");
    
                    ***more Code***
    
    	}
    	close(sockfd);
    	return 0; 
    }
    

    Viel Text für eine kurze Frage, ich hoffe ich konnte mein Problem deutlich machen und jemand hat eine Lösung für mich.

    Viele Grüße,
    Pingu



  • Du hast da eine Variable namens cli_addr...



  • Ist mir bekannt, bloß wie les ich da die IP aus? Hab schon mit inet_ntoa() und konsorten rumgespielt aber nichts brauchbares rausbekommen.
    Ich brauche die Adresse wenn möglich als String



  • inet_ntoa klingt schon nicht verkehrt. Wenn du jetzt noch etwas genauer werden könntest als

    P!ngu schrieb:

    rumgespielt aber nichts brauchbares rausbekommen

    könnte man dir sogar weiterhelfen.



  • In der FAQ ist etwas (vielleicht) brauchbares:

    http://www.c-plusplus.net/forum/viewtopic.php?p=316499



  • Hi,

    @MFK
    rumgespielt meint "try and error". Habe einfach alles mögliche (cli_addr. ...) in inet_ntoa() geworfen und geschaut was dabei rauskommt. Allerdings gabs entweder Fehler oder es wurde ein "int" zurückgegeben.
    Ich hab natürlich bereits geschaut wie die Strukturen aussehen, aus denen ich da die Information ziehen möchte.Allerdings blick ich da nicht ganz durch, in der Struktur gibts dann ne Struktur, mit nem Zeiger auf n Array von Zeigern und noch mehr Strukturen... 😕

    @gigg
    danke für den Hinweis

    der für mich relevante Teil ist wohl folgender...

    struct sockaddr_in *i;
    
      ...
    
      i = (struct sockaddr_in*)&ifa.ifr_addr; 
      puts (inet_ntoa(i->sin_addr));
    

    allerdings hilft mir das nicht weiter, da bei mir ja folgende Situation vorliegt...

    struct sockaddr_in serv_addr, cli_addr;
    

    Vermutlich gibts da ne ganz einfache Lösung, aber ich bin relativ neu in C und insbesondere Zeigern und Strukturen.



  • Hallo,

    puts (inet_ntoa(cli_addr.sin_addr));
    

    MfG,

    Probe-Nutzer



  • puts (inet_ntoa(serv_addr.sin_addr));
    puts (inet_ntoa(cli_addr.sin_addr));
    

    foo->bar ist kurz für *(foo).bar



  • @Probe-Nutzer, Insider

    naja soviel das foo->bar = (*foo).bar ist weiß ich dann doch.

    leider ist mein cli_addr aber kein Zeiger, sondern nur eine Variable, weshalb

    puts (inet_ntoa(cli_addr.sin_addr));
    

    nicht funktioniert.

    gcc sagt dazu folgendes...

    $ gcc ./open_socket.c -lpthread -o ./open_socket
    ./open_socket.c: In Funktion »main«:
    ./open_socket.c:84:1: Warnung: Übergabe des Arguments 1 von »puts« erzeugt Zeiger von Ganzzahl ohne Typkonvertierung [standardmäßig aktiviert]
    /usr/include/stdio.h:692:12: Anmerkung: »const char *« erwartet, aber Argument hat Typ »int«
    


  • Der Fehler, den gcc ausgibt, hat überhaupt nichts damit zu tun, dass cli_addr kein Zeiger ist. Zeige besser die Zeile 84, damit klar ist, was das Problem ist. Dort verwendest du offensichtlich nicht inet_ntoa (denn das gibt keine Ganzzahl zurück, wie gcc feststellt), sondern...?

    MfG,

    Probe-Nutzer



  • Zeile 84 ist

    puts (inet_ntoa(cli_addr.sin_addr));
    

    dachte das wäre aus meinem Post ersichtlich.



  • Ok, dann noch einmal ganz genau, warum ich anzweifeln musste, dass das die richtige Zeile ist (dein main oben hat z.B. auch nur 54 Zeilen) : die angegebene Zeile kann die Warnung (nicht Fehler, wie ich oben schrieb) nicht verursachen, weil inet_ntoa, wie nachzulesen ist, char* zurück gibt, und keine Ganzzahl, nicht die Übergabe von cli_addr.sin_addr an inet_ntoa ist das Problem, sondern das puts einen int bekommt, den inet_ntoa nicht als Ergebnis liefern kann. Hast du irgendwo noch etwas mit inet_ntoa stehen, hast du über main noch etwas, was das verursachen könnte?

    MfG,

    Probe-Nutzer



  • woanders im Programm wird weder inet_ntoa() noch puts benutzt, lediglich zum testen an folgender Stelle (für gesamten Codeausschnitt siehe Eröffnungspost)

    ...
       while (1)
       {
            bzero(command,255);     //initialisiere command buffer
            listen(sockfd, 5);     //int listen(int socket, int backlog) - backlog, something with the queue
            clilen = sizeof(cli_addr);  //Länge der client addresse
            newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    
    ----->  puts (inet_ntoa(cli_addr.sin_addr));
    
            read(newsockfd,command,255);
    ...
    


  • Include vergessen?



  • sähe da die Meldung von gcc nicht anders aus?
    hier die includes...

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h> 
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <pthread.h>
    


  • P!ngu schrieb:

    sähe da die Meldung von gcc nicht anders aus?

    Ich bin nicht so der C-Fachmann, aber war das im alten Standard nicht so, dass undeklarierte Funktionen als Rückgabetyp int angenommen werden? Das würde zur Fehlermeldung passen

    P!ngu schrieb:

    hier die includes...

    man inet_ntoa erwähnt noch

    #include <arpa/inet.h>



  • damit funktionierts! 🤡

    Vielen Dank MFK

    hier nochmal kurz die Zusammenfassung...

    Situation: Client hat sich bereits mit Server verbunden.
    Frage: Wie bekomme ich auf Serverseite die IP vom Client als String?
    Antwort: so...

    ...
    #include <arpa/inet.h>
    
    ...
    
    int main(int argc, char *argv[])
    {
            ...
    
            struct sockaddr_in serv_addr, cli_addr;	
    
            ...
    
    	while (1)
    	{
                    ...
    
    		listen(sockfd, 5);
    		clilen = sizeof(cli_addr);
    		newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    
    puts (inet_ntoa(cli_addr.sin_addr));
    
                    ...
    

    Vielen Dank auch an alle anderen die mir hier geholfen haben.

    Schönes Wochenende,
    Pingu 🙂


Anmelden zum Antworten