Unix socket, Verbindung geht nicht



  • Hallo,
    ich wollte mal einen "Unix socket" schreiben, nur leider funktioniert das Ding was ich nun hab nicht - ich hab den server/client aus mehreren Tutorials zusammengeklebt und kompiliere beide auf Debian/Linux. Der client schafft einfach keinen Verbindungsaufbau. Irgendwie ist mir das noch etwas zu undurchsichtig, wie das bei AF_Unix genau laeuft. Der Code compiliert.

    Warum kann ich mich nicht connecten?

    // server.c
    /*
      demonstrates the creation and use of a unix socket - AF_UNIX!!!
    //*/
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/un.h>
    #include <unistd.h>
    
    #define NUMBER_OF_STRINGS 3
    #define ADDRESS_TO_CONNECT "mysocket"
    #define RECEIVED_SIZE 50
    
    char* strings[NUMBER_OF_STRINGS] = {
      "this is the first string form the server.\n", 
      "this is the second string from the server.\n",
      "this is the third string from the server.\n"
    };
    
    int main(int argc, char** argv)
    {
      // socket
      register int sockd=0;
      if(0 > (sockd = socket(AF_UNIX, SOCK_STREAM, 0))){
        perror("socket failed");
        exit(EXIT_FAILURE);
      }
    
      // address for the server - Unix (cast to sockaddr possible)
      struct sockaddr_un addr_server;
      addr_server.sun_family = AF_UNIX;
      strncpy(addr_server.sun_path, ADDRESS_TO_CONNECT, strlen(ADDRESS_TO_CONNECT) + 1);
      unlink(ADDRESS_TO_CONNECT);  
    
      // bind server to the address
      register int len_addr = sizeof(addr_server.sun_family) + strlen(addr_server.sun_path);
      if(0 > bind(sockd, (struct sockaddr*) &addr_server, len_addr)){
        perror("bind failed");
        exit(EXIT_FAILURE);
      }
    
      // listen on the socket
      if(0 > listen(sockd, 5)){
        perror("listen failed");
        exit(EXIT_FAILURE);
      }
    
      /*
        without loop accept() blocks and waits until it
        receives a client request to connect to
      //*/
    
      char strReceived[RECEIVED_SIZE];
      while(1){  
    
        // accept clients
        register int clientd=0;
        struct sockaddr_un addr_client;
        unsigned int len_addr_from=0;
        if(0 > (clientd = accept(sockd, (struct sockaddr*) &addr_client, &len_addr_from))){
          perror("accept failed");
          exit(EXIT_FAILURE);
        }
    
        puts("connected");
    
        unsigned int done=0;
        do{
          memset(strReceived, '\0', RECEIVED_SIZE);
          register int bytes=0;
          if(0 > (bytes = recv(clientd, strReceived, RECEIVED_SIZE, 0))){
    	perror("recv failed");
    	done = 1;
          }else{
    	puts(strReceived);
          }
    
          if(!done){
    	register int idx=0;
    	for(idx=0; idx<NUMBER_OF_STRINGS; ++idx){
    	  if(0 > send(clientd, strings[idx], strlen(strings[idx]), 0)){
    	    perror("send failed");
    	    done = 1;
    	  }
    	}
          }
    
        }while(!done);      
      }// transfer block  
    
      // over and close
      puts("READY.");
      close(sockd);
      exit(EXIT_SUCCESS);
    }
    
    // client.c
    /*
      demonstrates the creation and use of a unix socket - AF_UNIX!!!
    //*/
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/un.h>
    #include <unistd.h>
    
    #define NUMBER_OF_STRINGS 3
    #define ADDRESS_TO_CONNECT "mysocket"
    
    char* strings[NUMBER_OF_STRINGS] = {
      "this is the first string form the client.\n", 
      "this is the second string from the client.\n",
      "this is the third string from the client.\n"
    };
    
    int main(int argc, char** argv)
    {
      // socket
      register int sockd=0;
      if(0 > (sockd = socket(AF_UNIX, SOCK_STREAM, 0))){
        perror("socket failed");
        exit(EXIT_FAILURE);
      }
    
      // address - Unix (cast to sockaddr possible!)
      struct sockaddr_un addr_server;
      addr_server.sun_family = AF_UNIX;
      strncpy(addr_server.sun_path, ADDRESS_TO_CONNECT, strlen(ADDRESS_TO_CONNECT) + 1);
    
      // connect
      register int len_addr_server = sizeof(addr_server.sun_family) + strlen(addr_server.sun_path);
      if(0 > (connect(sockd, (struct sockaddr*) &addr_server, len_addr_server))){
        perror("connect failed");
        exit(EXIT_FAILURE);
      }
    
      puts("connected");
    
      // set the filepointer to the socket
      FILE* fp = fdopen(sockd, "r"); // TODO: discard
    
      {
        // read some strings
        char c;
        register int idx=0;
        for(idx=0; idx < NUMBER_OF_STRINGS; ++idx){
          while(EOF != (c = fgetc(fp))){
    	putchar(c);
    	if(c == '\n')
    	  break;
          }
        }
    
        // now send
        for(idx=0; idx < NUMBER_OF_STRINGS; ++idx){
          send(sockd, strings[idx], strlen(strings[idx]), 0);
        }    
      } // transfer block
    
      // close the socket
      puts("READY.");
      close(sockd);
      exit(EXIT_SUCCESS);
    }
    


  • Ich habe zwar noch nicht mit AF_UNIX sondern nur mit PF_INET gearbeitet, aber trotzdem glaube ich zu wissen, wo das Problem liegt: Bein Binden des Sockets an einen Port stellst Du keinen Port ein! Bei dem Client-Programm ebenfalls nicht. Daher wird dein Socket an irgendeinen Port gebunden und der Client kontaktiert irgendeinen anderen Port. So können sie sich ja nicht finden!

    Was also fehlt ist etwas in der Art:

    addr_server.sun_port = htons([i]Port-Nummer[/i]);
    

    (Zumindest bei PF_INET Sockets ist das so.)



  • @Martin G

    ich kritisier andere leute nur sehr ungern, aber für jemanden, der sich Dr.Ing. nennt und auch noch ein buch über c und linux herausgebracht hat, hast du ja echt null plan. pf_local und ports... es is echt kaum zu fassen...



  • Martin G schrieb:

    ...glaube ich zu wissen, wo das Problem liegt...

    kritisierer schrieb:

    @Martin G ...es is echt kaum zu fassen...

    An den Kritisierer:
    So wie ich es verstanden habe war es keine definitive Aussage, sondern nur eine Vermutung und ich bin fuer jede Vermutung dankbar! Nja, zu Buechern i.allg. - kA wieviele Beispiele in Buechern wie u.a. sogar Sedgewicks Algorithmen, Marshall's Unix C, etc ich da schon gefunden hab, die sich so einfach nich kompilieren lassen. Obiges Beispiel ist auch irgendso nem Schinken entlehnt. Gibt es eigentlich auch Buecher mit funktionierendem Code, fraegt man sich da manchmal wirklich? Naja, ich finde das jedenfalls mittlerweile schon ganz normal, andere Buecher haben Aufgaben drin, C Buecher haben halt nichtfunktionierende Beispiele. Man lernt durch debuggen derselbigen. 😉

    Der Fehler oben liegt wo ganz anders. Abgesehn, dass ich den Code nun etwas erweitert habe und die hier praesentierte Version nur bezueglich des geposteten Problems korrigieren will: beide Files beziehen sich auf "mysocket", dabei wird ein File "mysocket" angelegt und geschrieben. Da ich natuerlich bloederweise server.c im Ordner Server und client.c im Ordner Client hatte, kann das so nix werden. Beide legen "mysocket" local ihrem Ordner an und somit wartet ein Server ewig und ein Client sucht und findet keinen richtigen Server, fasst wie im richtigen Leben mit den Jungs und Maedels.. - die Strategie hier bei den Sockets ist zumindest sowas wie "/tmp/mysocket" herzunehmen einerseits, und andererseits die #defines in ein extern, gemeinsam einkompiliertes unixsocketdefinekram.h File zu schreiben.

    Ein grosser Unterschied imho von AF_UNIX zu AF_INET (oder PF_INET, eben) ist, dass es sich bei AF_UNIX um Interprozesskommunikation handelt! Also um eine Methode zwischen zwei Prozessen im gleichen System zu kommunizieren. Und das eben nur ueber Sockets, aehnlich wie die Kommunikation von versch. Systemen ueber Netzwerke. Ich weiss nicht ob es noch andere IPC Sockets gibt, in der BSD Socketkiste, aber ich denke dass die AF_UNIX damit schon ne gewisse Sonderrolle haben 😉

    Danke fuer Eure Antworten 👍



  • kritisierer schrieb:

    @Martin G
    ich kritisier andere leute nur sehr ungern, aber für jemanden, der sich Dr.Ing. nennt und auch noch ein buch über c und linux herausgebracht hat, hast du ja echt null plan. pf_local und ports... es is echt kaum zu fassen...

    @kritisierer:
    Wie schon in meinem Beitrag stand, habe ich bislang nur mit INET-Sockets gearbeitet und lediglich vermutet, dass es auch bei AF_UNIX etwas wie "Ports" gäbe. Ich finde daher Deinen Kommentar nicht nur ziemlich blöde, sondern auch für "Fabeltier" absolut unnütz!
    Zu Deiner Bemerkung bezüglich "Dr.-Ing." und meinem Buch: Ich behaupte mal, dass ich eine ganze Menge über Linux weiß, von dem Du keine Ahnung hast -- nur eben mit AF_UNIX-Sockets habe ich noch nicht gearbeitet.



  • Hallo hey beruhigt euch doch mal. Also das es Unterschiede zwischen Linux und Windows gibt ist klar. Soweit wie ich es weiß ist es AF_UNIX PF_INET identisch.
    Versuche mal den folgenden Link dort werden viele Fuinktioenn für die Socket - Programmierung beschrieben.

    http://www.zotteljedi.de/doc/socket-tipps/index.html



  • Nein, die Typen AF_INET und AF_UNIX sind nicht identisch (verdammte Axt :D) (und wo von Unterschieden zwischen Windows und Linux die Rede war, sehe ich auch nicht)

    Und was die Sonderrolle angeht, nunja, eigentlich sind alle Sockets nach oben hin gleich. Sie haben eine Kennung (PF_*), eine dazugehörige Adresse (INET -> sockaddr_in, UNIX -> sockaddr_un, INET6 -> sockaddr_in6), einen Typ (Stream, Datagram, Raw, ...), bei Verbindungsorientierung zwei Endpunkte (bind und connect) usw. Dass eine Adresse ohne "Hausnummer" eine Sonderrolle darstellt, ist nirgendwo definiert 😉

    @Fabeltier:
    Das urspr. Problem hat sich also erledigt?


Anmelden zum Antworten