tcp server send/recv



  • hab ich das richtig verstanden?
    wenn man recv... in ne while schleife packt läuft diese solange der socket verbunden ist

    jedoch läuft sie nur durch wenn etwas empfangen wird



  • Was genau ist jetzt Deine Frage?

    btw, recv wartet einfach nur weiter auf Nachrichten, wenn gerade keine verfügbar sind, bzw. gibt bei nicht-blockierenden Sockets -1 zurück und setzt errno auf EAGAIN.



  • kann ich in der schleife auch was senden wenn nichts empfangen wurde?



  • debian inside schrieb:

    kann ich in der schleife auch was senden wenn nichts empfangen wurde?

    Nein. recv blockiert, wenn nichts kommt. Da musst du dann schon mit Threads
    oder mehreren eigentstaendigen Prozessen arbeiten.

    Warum informiert ihr Leute euch nicht vorher? Versteh mich nicht falsch, dass
    soll niemanden davon abhalten fragen zu stellen, aber das ist Basiswissen,
    was die Materie angeht und das sollte man schon wissen. Mal davon
    abgesehen, dass das in jedem Buch und auch in den Manpages steht.

    mfg
    v R



  • virtuell Realisticer schrieb:

    Nein. recv blockiert, wenn nichts kommt. Da musst du dann schon mit Threads
    oder mehreren eigentstaendigen Prozessen arbeiten.

    Das stimmt so nicht! Der Socket ist ein File-Handle; mit select() kann man abfragen, ob Daten anliegen oder nicht. Damit lässt sich ein TCP/IP-Server auch in einem Thread programmieren.
    In der 3. Auflage von C und Linux, die nächsten Monat erscheint, ist ein Beispielprogramm mit einem interaktiven TCP/IP-Server, der Zeichen, die über die Tastatur eingegeben werden, sendet und gleichzeitig empfangene Daten auf dem Bildschirm ausgibt - das Ganze ist ohne Threading und fork().
    Wenn's interessiert, kann ich den Quelltext ja mal posten.

    Richtig ist, dass "normale" TCP/IP-Server wie beispielsweise HTTP-Server mit mehreren Threads / Prozessen arbeiten.

    Martin



  • ein thread pro client wäre übersichtlicher...

    kannst du den quelltext bitte posten



  • Voilà:

    /*
        server.c - interaktiver Netzwerk-Server
    */
    
    # include <stdio.h>
    # include <string.h>
    # include <unistd.h>
    # include <sys/types.h>
    # include <sys/socket.h>
    # include <netinet/in.h>
    # include <arpa/inet.h>
    
    void err_exit(char *message)
     {
      perror(message);
      exit(1);
     }
    
    int main(int argc, char *argv[])
     {
      static char buffer[256];
      int sock_fd, client_fd, err, addr_size, length, port;
      struct sockaddr_in my_addr, client_addr;
      fd_set input_fdset;
    
      if ((argc != 2) || (strcmp(argv[1], "-h") == 0))
       {
        fprintf(stderr, "Usage: server port\n");
        return(1);
       }
    
      if (sscanf(argv[1], "%d", &port) != 1)
       {
        fprintf(stderr, "server: Bad port number.\n");
        return(1);
       }
    				   /*--- socket() ---*/
      sock_fd = socket(PF_INET, SOCK_STREAM, 0);
      if (sock_fd == -1)
        err_exit("server: Can't create new socket");
    
      my_addr.sin_family = AF_INET;
      my_addr.sin_port = htons(port);
      my_addr.sin_addr.s_addr = INADDR_ANY;
    
    				   /*--- bind() ---*/
      err = bind(sock_fd, &my_addr, sizeof(struct sockaddr_in));
      if (err == -1)
        err_exit("server: bind() failed");
    
    				   /*--- listen() ---*/
      err = listen(sock_fd, 1);
      if (err == -1)
        err_exit("server: listen() failed");
    
    				   /*--- accept() ---*/
      addr_size = sizeof(struct sockaddr_in);
      client_fd = accept(sock_fd, &client_addr, &addr_size);
      if (client_fd == -1)
        err_exit("server: accept() failed");
      printf("I'm connected from %s\n", inet_ntoa(client_addr.sin_addr));
    
      while (1)
       {
        FD_ZERO(&input_fdset);
        FD_SET(STDIN_FILENO, &input_fdset);
        FD_SET(client_fd, &input_fdset);
        if (select(client_fd+1, &input_fdset, NULL, NULL, NULL) == -1)
          err_exit("server: select() failed");
        if (FD_ISSET(STDIN_FILENO, &input_fdset))
         {
          if (fgets(buffer, 256, stdin) == NULL)
           {
            printf("server: Closing socket.\n");
            break;
           }
          length = strlen(buffer);
          send(client_fd, buffer, length, 0);
         }
        else
         {
          length = recv(client_fd, buffer, 256, 0);
          if (length == 0)
           {
            printf("Connection closed by remote host.\n");
            break;
           }
          write(STDOUT_FILENO, buffer, length);
         }
       }
      close(client_fd);
      close(sock_fd);
      return(0);
     }
    

    Mit dem Programm kannst du mal von Hand Webserver spielen 😉
    Als Parameter musst du dem Programm die zu bindende Port-Nummer angeben (also als Webserver 80).
    Wie gesagt, mehr dazu findest du ab Februar in der 3. Auflage von "C und Linux", Hanser Verlag.

    Martin


Anmelden zum Antworten