Sieťové prepojenie - program v C

Sekcia: Aplikácie & Desktop 09.01.2013 | 10:41
Avatar ferri Fedora  Používateľ
Ako programátor náturista som dostal zadanie naprogramovať v jazyku C pod linuxom program sieťového prepojenia dvoch počítačov. Keďže tejto problematike som sa nikdy predtým nevenoval našiel som na internete tieto dva návody.

http://shoe.bocks.com/net/
http://www.linuxjournal.com/article/2333

Keďže sú to už staršie články, chcel som sa opýtať na ich aktuálnosť, prípadne na doporučenia na iné články/návody.
    • Re: Sieťové prepojenie - program v C 09.01.2013 | 18:12
      Avatar Fridolín Pokorný Fedora 21  Používateľ
      Na tejto nizkej urovni sa v podstate uz roky nediali zavaznejsie zmeny. Snad len prichod IPv6 (vid getaddrinfo() apod.). Odporucal by som este manualove stranky. Tie su o socketoch a programovanim v nich pomerne dopre spracovane.
      • Re: Sieťové prepojenie - program v C 09.01.2013 | 20:23
        johnny   Návštevník
        inet_aton inet_ntoa...
    • Re: Sieťové prepojenie - program v C 09.01.2013 | 20:30
      johnny   Návštevník
      http://www.builder.cz/rubriky/c/c--/sokety-a-c--156186cz

      Ale ak by si chcel písať programy, ktoré už budú kompatibilné aj s IPv6 a nie len IPv4 tak to ti potom odporúčam prečítať neskôr aj niečo novšie.
      • Re: Sieťové prepojenie - program v C 09.01.2013 | 21:41
        Avatar ferri Fedora  Používateľ
        Veľká vďaka všetkým.
        Ospravedlňujem sa za nechtiac zle zvolenú sekciu na fóre.
    • Re: Sieťové prepojenie - program v C 09.01.2013 | 20:32
      johnny   Návštevník
      Ak budeš chcieť podrobne vedieť o tých funkciách, tak už len stačí zadať man <funkcia> do googla a on už ti poradí. Ak píšeš pre windows tak môžeš skúsiť msdn.
      • Re: Sieťové prepojenie - program v C 09.01.2013 | 21:46
        Avatar ferri Fedora  Používateľ
        To stačí zadať aj do konzoly. ;-)
        Kompilujem v konzole, takže je to operatívnejšie.
    • Re: Sieťové prepojenie - program v C 18.01.2013 | 17:39
      Avatar ferri Fedora  Používateľ
      Pridávam výpis hotových zdrojových súborov.

      serverová aplikácia
      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      #include <unistd.h>
      #include <arpa/inet.h>
      #include <sys/types.h>
      #include <netinet/in.h>
      #include <sys/socket.h>

      #define MAXRCVLEN 500

      int main(int argc, char *argv[])
      {
      struct sockaddr_in dest; /* socket info about the machine connecting to us */
      struct sockaddr_in serv; /* socket info about our server */
      int mast_socket; /* socket used to listen for incoming connection */
      int con_socket; /* socket used for accepted connection */
      char buffer[MAXRCVLEN + 1]; /* +1 so we can add null terminator */
      int len; /* amount of sent or received data */
      int port; /* port number */
      socklen_t socksize = sizeof(struct sockaddr_in);

      /* start program with port number */
      if (argc != 2) {
      fprintf(stderr, "Usage %s <port>\n", argv[0]);
      return 1;
      }
      port = atoi(argv[1]);

      /* create the master socket and check it worked */
      if ((mast_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
      perror("Creating master socket");
      exit(EXIT_FAILURE);
      }

      /* zero the struct before filling the fields */
      memset(&serv, 0, sizeof(serv));
      serv.sin_family = AF_INET; /* set the type of connection to TCP/IP */
      serv.sin_addr.s_addr = INADDR_ANY; /* set our address to any interface */
      serv.sin_port = htons(port); /* set the server port number */
      /* bind serv information to master socket */
      if (bind(mast_socket, (struct sockaddr *)&serv, socksize) == -1) {
      perror("bind()");
      return 1;
      }

      /* start listening, allowing a queue of up to 1 pending connection */
      if (listen(mast_socket, 1) == -1) {
      perror("listen()");
      return 1;
      }

      /* accept one connection */
      if ((con_socket = accept(mast_socket, (struct sockaddr *)&dest,
      &socksize)) == -1) {
      perror("accept()");
      return 1;
      }

      /* address of incomming connection */
      printf("Incoming connection from %s\n", inet_ntoa(dest.sin_addr));

      /* message "quit" ends receiving/sending data */
      while (strcmp(buffer, "quit\n") != 0) { /* received end */
      /* inserting data for sending */
      printf("Enter data for client: ");
      if (fgets(buffer, MAXRCVLEN, stdin) == NULL) {
      fprintf(stderr, "fgets()\n");
      return 1;
      }

      /* sending data */
      if ((len = send(con_socket, buffer, strlen(buffer), 0)) == -1) {
      perror("send()");
      return 1;
      }
      printf("Sent: %d bytes\n", len);

      /* it was sent message about end of connection */
      if (strcmp(buffer, "quit\n") == 0)
      break; /* finish at once */

      /* receiving data */
      if ((len = recv(con_socket, buffer, MAXRCVLEN, 0)) == -1) {
      perror("recv()");
      return 1;
      }
      /* have to null terminate the received data ourselves */
      buffer[len] = '\0';
      printf("From client: %s", buffer);
      printf("Received: %d bytes\n", len);
      }

      /* shutdown sockets properly */
      close(con_socket);
      close(mast_socket);

      return 0;
      }
      • Re: Sieťové prepojenie - program v C 18.01.2013 | 17:41
        Avatar ferri Fedora  Používateľ
        klientova aplikácia #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
        #include <unistd.h>
        #include <netdb.h>
        #include <arpa/inet.h>
        #include <sys/types.h>
        #include <netinet/in.h>
        #include <sys/socket.h>

        #define MAXRCVLEN 500

        int main(int argc, char *argv[])
        {
        char buffer[MAXRCVLEN + 1]; /* +1 so we can add null terminator */
        char *remote_host; /* server name or IP */
        int my_socket; /* socket used for connection */
        int len; /* amount of sent or received data */
        int remote_port; /* server port number */
        struct hostent *host_ptr; /* remote host */
        struct sockaddr_in dest; /* socket info about server to connect */
        socklen_t socksize = sizeof(struct sockaddr_in);

        /* start program with sever name/IP and port number */
        if (argc != 3) {
        fprintf(stderr, "Usage %s <server_host> <server_port>\n", argv[0]);
        return 1;
        }
        remote_host = argv[1];
        remote_port = atoi(argv[2]);

        /* resolve information about remote server */
        if ((host_ptr = gethostbyname(remote_host)) == NULL) { /* from name */
        if ((host_ptr = gethostbyaddr(remote_host, strlen(remote_host),
        AF_INET)) == NULL) { /* or from IP number */
        perror("Error resolving server address");
        return 1;
        }
        }

        /* create socket and check it worked */
        if ((my_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("Creating socket");
        return 1;
        }

        /* zero the struct before filling the fields */
        memset(&dest, 0, sizeof(dest));
        dest.sin_family = AF_INET; /* set the type of connection to TCP/IP */
        dest.sin_port = htons(remote_port); /* set destination port number */
        /* set destination IP address */
        memcpy(&(dest.sin_addr.s_addr), host_ptr->h_addr, host_ptr->h_length);

        /* connect socket */
        if (connect(my_socket, (struct sockaddr *)&dest, socksize) == -1) {
        perror("connect()");
        return 1;
        }

        /* message "quit" ends receiving/sending data */
        while (strcmp(buffer, "quit\n") != 0) { /* sent end */
        /* receiving data */
        if ((len = recv(my_socket, buffer, MAXRCVLEN, 0)) == -1) {
        perror("recv()");
        return 1;
        }
        /* have to null terminate the received data ourselves */
        buffer[len] = '\0';
        printf("From server: %s", buffer);
        printf("Received: %d bytes\n", len);

        /* it was received message about end of connection */
        if (strcmp(buffer, "quit\n") == 0)
        break; /* finish at once */

        /* inserting data for sending */
        printf("Enter data for server: ");
        if (fgets(buffer, MAXRCVLEN, stdin) == NULL) {
        fprintf(stderr, "fgets()\n");
        return 1;
        }
        /* sending data */
        if ((len = send(my_socket, buffer, strlen(buffer), 0)) == -1) {
        perror("send()");
        return 1;
        }
        printf("Sent: %d bytes\n", len);
        }

        /* shutdown socket properly */
        close(my_socket);

        return 0;
        }
    • Re: Sieťové prepojenie - program v C 20.01.2013 | 13:37
      Avatar ferri Fedora  Používateľ
      Na testovanie vytvorených programov sieťového prepojenia používam počítač s nainštalovanou Fedora 17. Druhý zapožičaný počítač beží z live cd Kubuntu 9.10 kvôli jeho veku. Počítače sú prepojené sieťovým káblom. Mám aj krížený, ale netreba. Spojenie funguje aj na obyčajnom.

      Na Fedora 17 nastavujem sieťovú kartu cez
      ifconfig eth0 192.168.1.1 netmask 255.255.255.0 up
      Na Kubuntu
      ifconfig eth0 192.168.1.2 netmask 255.255.255.0 up

      Paradox je, že spojenie funguje iba v prípade, že na Kubuntu spustím serverovú aplikáciu a na Fedore spustím klientovu aplikáciu. Opačne to nefunguje.
      Skúsil som aj navzájom vymeniť IP adresy, ale nepomohlo. Stále musím na Kubuntu spustiť serverový program a na Fedore klientov program.

      Vedel by mi niekto poradiť, prečo to tak je?
      • Re: Sieťové prepojenie - program v C 20.01.2013 | 17:44
        WlaSaTy   Návštevník
        Odpoveď prečo to tak je sa skrýva v magickom makre na prácu s chybami. Skús si pozrieť príkaz man 3 errno a k nemu prislúchajúci man 3 strerror.

        Je dosť možné, že sa triafaš na už obsadené porty, alebo nemáš právo na vytvorenie konekcie na porte pod 1024.
        • Re: Sieťové prepojenie - program v C 20.01.2013 | 18:22
          Avatar ferri Fedora  Používateľ
          Ak si pozrieš uvedené listingy programov, errno v programoch používam.

          Podotýkam, že programy fungujú správne, ako som vyššie uviedol.
          Lenže len pri kombinácií server - live cd, klient - installed system.

          Kombinácia klient - live cd, server - installed system vypíše cez perror hlášku
          Connection refused .

          Pokiaľ testujem server/klient na localhost-e fungujú v jednom aj druhom poradí bez problémov.

          Nanešťastie nemám k dispozícií dva plnohodnotné systémy s plnou inštaláciou, takže neviem identifikovať, či správanie sa programov je dané druhým live systémom alebo nie.

          • Re: Sieťové prepojenie - program v C 20.01.2013 | 18:45
            WlaSaTy   Návštevník
            Ty errno nepouzívaš. Ty si len skontroluješ, či sa akcia vykonala. A v prípade že nie, tak vypíšeš cez perror nejakú správu na chybový výstup.

            Bez toho že si pozrieš kód chyby, a preložíš si to do textu, tak nebudeš vedieť v čom je chyba. A reagovanie na základe odhadu z čítania kryštáľovej gule má posledný príslevok. Skontroluj si firewall či neblokuješ pripojenie. Chyba connection refused má množstvo dôvodov.
            • Re: Sieťové prepojenie - program v C 20.01.2013 | 19:59
              Avatar ferri Fedora  Používateľ
              Zdá sa, že si nerozumieme. Funkcia perror() vypisuje chybové reťazce takým spôsobom, že naskôr vypíše komentár uvedený v zátvorke, potom nasleduje dvojbodka a až potom je výpis podľa errno.
              Napr. výstup z tohto programu
              #include <stdio.h>
              #include <string.h>
              #include <errno.h>
              
              int main(void)
              {
                errno = ENOENT;
                perror("perror");
                printf("strerror %s\n", strerror(ENOENT)); 
                
                return 0;
              }
              bude
              perror: No such file or directory
              strerror No such file or directory


              Funkcia perror() umožňuje obohatiť výpis podľa errno o vlastný komentár.
              • Re: Sieťové prepojenie - program v C 20.01.2013 | 20:21
                WlaSaTy   Návštevník
                To je dosť možné. Posledne, keď som pracoval s perror, tak sa jednalo len o makro ktoré vypísalo správu predanú v parametri na file deskriptor 2, teda na chybový výstup.

                Ale, to nič nemení na tom, že si tie ostatné veci neskontroloval. Takže, s radosťou do toho.
                • Re: Sieťové prepojenie - program v C 20.01.2013 | 21:28
                  Avatar ferri Fedora  Používateľ
                  Nepriamo si mi vnukol myšlienku nahodiť na oba počítače rovnaké live systémy, keďže sa mi nechcelo vŕtať v zabezpečení dobre fungujúcej Fedora 17.
                  Nahodil som na oba počítače Kubuntu 9.10 live, prepojil káblom, nastavil IPčky, nahral cez USB skomplivané programy server_tcp a client_tcp. Spustil som tak aj naopak a fungovalo bez problémov.

                  Takže problém bol v zabezpečení Fedora 17.
                  Programy sú v poriadku.