Il est difficile de mettre en place un serveur en langage c. Le but de cet article est de permettre aux nouveaux arrivants et aux personnes qui n'ont jamais écrit de serveur de le déplacer pour le moment et de répondre dans une certaine mesure à quelques questions. Si vous devez créer un serveur et travaillez actuellement, vous pouvez gagner du temps en copiant le code ci-dessous et en le réécrivant selon les spécifications de votre entreprise. Cette fois, ce sera très simple en UDP. Je pense que cela peut ne pas être suffisant pour les besoins réels. Cependant, il est plus facile d'avancer lorsque vous êtes connecté que lorsque vous n'avez ni mains ni jambes. À partir de là, jouez avec le code qui correspond à vos besoins. Il n'y a aucune explication dans cet article sur ce qu'est UDP. Il y a tellement d'explications sur Internet qu'elles sont pourries, alors veuillez les utiliser. Pour les livres, «Computer Network 5th Edition» est bon, mais le prix et l'épaisseur sont si ...
Je vais mettre l'environnement que j'ai essayé pour le moment, mais je pense qu'il fonctionnera avec des linux relativement récents.
Ubuntu 18.04.2 LTS
gcc 7.4.0
Du point de vue de la mise en œuvre, UDP peut être considéré comme un simple TCP.
En tant que simple serveur
localhost`` 9002
--Afficher les données reçuesPour le moment, le code qui fonctionne si vous le copiez et le collez ressemble à ceci.
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
int main ()
{
  //1.Créer une adresse de réception
  struct addrinfo hints;
  memset (&hints, 0, sizeof (hints));
  hints.ai_socktype = SOCK_DGRAM;
  struct addrinfo *bind_address;
  getaddrinfo ("localhost", "9002", &hints, &bind_address);
  //2.Créer une prise
  int  socket_listen;
  socket_listen = socket (bind_address->ai_family,
              bind_address->ai_socktype,
              bind_address->ai_protocol);
  if (socket_listen < 0)
  {
      fprintf (stderr, "socket() failed. (%d)\n", errno);
      return 1;
  }
  //3.Liez l'adresse locale au socket
  if (bind (socket_listen, bind_address->ai_addr, bind_address->ai_addrlen))
  {
      fprintf (stderr, "bind() failed. (%d)\n", errno);
      return 1;
  }
  freeaddrinfo (bind_address);
  //4.Attendez la connexion client
  while (1)
  {
      struct sockaddr_storage client_address;
      socklen_t client_len = sizeof (client_address);
      char read[4096];
      memset(read, 0, sizeof(read));
      int bytes_received = recvfrom (socket_listen, read, 4096, 0,
                     (struct sockaddr *) &client_address,
                     &client_len);
      if (bytes_received < 1)
      {
        fprintf (stderr, "connection closed. (%d)\n", errno);
        return 1;
      }
      printf("receiving: %s", read);
  }
  //5.Fermer la prise
  close(socket_listen);
  printf ("Finished.\n");
  return 0;
}
Il existe plusieurs façons de créer une structure de connexion.
gethostbyname
--Comment utiliser la fonction getaddrinfoCette fois, je l'ai construit par la troisième méthode.
Il y a trois tâches pour utiliser la fonction getaddrinfo.
La «structure addrinfo» en 3 définit généralement ip4 ou ip6, TCP ou UDP.
Si ip vaut 0, il devient ip4.
SOCK_DGRAM est un datagramme, et lorsqu'il est défini, il devient UDP.
Je ne l'ai pas utilisé cette fois, mais la valeur de retour de la fonction getaddrinfo est errno, donc si vous le faites correctement, vous devriez la recevoir.
C'est celui qui écrit avec une habitude aussi complète, peu importe qui le fait.
Un socket est un terminal de communication (sur un programme), et le système d'exploitation envoie et reçoit via le socket.
La fonction socket crée un descripteur de socket.
Un descripteur de socket est un type de descripteur de fichier.
Un descripteur de fichier est un numéro unique qui permet au système d'exploitation de gérer les fichiers.
linux traite diverses choses comme des fichiers.
Fichiers texte, périphériques (comme une clé USB), etc.
Pour pouvoir lire et écrire sur le réseau de la même manière que des fichiers
C'est le rôle du descripteur de socket.
La valeur de retour de la fonction socket est le descripteur de socket.
C'est aussi une habitude.
Associez l'adresse reçue par la fonction de liaison au socket.
Vous êtes maintenant prêt à recevoir.
Le processus le plus important.
Je suis sûr que nous allons faire diverses choses ici dans ce chan.
Normalement, le serveur n'est pas abandonné, donc il boucle indéfiniment.
Utilisez la fonction recvfrom pour recevoir.
La fonction recvfrom reçoit les informations source.
La structure sockaddr_storage est une structure qui peut être représentée par ip4 ou ip6.
Comme la mémoire et les threads, les sockets fuient, vous devez donc les ouvrir.
La fonction de fermeture est utilisée pour fermer le fichier.
Puisque le socket peut également être traité comme un fichier, il peut être ouvert avec la même «fonction de fermeture» que le fichier.
J'ai l'impression que je n'en ai pas besoin. Je lis la fonction de connexion même si c'est UDP. En fait, vous pouvez utiliser la fonction de connexion dans UDP. Vous pouvez également écrire à l'aide de la fonction de connexion sur le serveur. Lorsque vous utilisez la fonction de connexion dans UDP, elle se comporte différemment lorsque vous l'utilisez dans TCP. L'explication ici est ... eh bien.
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
    struct addrinfo hints;
    memset(&hints, 0, sizeof(hints));
    hints.ai_socktype = SOCK_DGRAM;
    struct addrinfo *peer_addr;
    if(getaddrinfo("localhost","9002",&hints, &peer_addr))
    {
        fprintf(stderr, "getaddrinfo() failed. (%d)\n", GETSOCKETERRNO());
        return 1;
    }
    char addrbuf[100];
    char servbuf[100];
    getnameinfo(peer_addr->ai_addr, peer_addr->ai_addrlen, addrbuf, sizeof(addrbuf), servbuf, sizeof(servbuf), NI_NUMERICHOST);
    printf("%s %s\n", addrbuf, servbuf);
    puts("Creating socket");
    int socket_peer;
    socket_peer = socket(peer_addr->ai_family, peer_addr->ai_socktype, peer_addr->ai_protocol);
    if(!ISVALIDSOCKET(socket_peer))
    {
        fprintf(stderr, "socket() failed. (%d)\n", GETSOCKETERRNO());
        return 1;
    }
    if(connect(socket_peer,peer_addr->ai_addr, peer_addr->ai_addrlen))
    {
        fprintf(stderr,"connect() failed. (%d).\n", GETSOCKETERRNO());
        return 1;
    }
    freeaddrinfo(peer_addr);
    puts("Connected");
    while(1)
    {
        {
            char read[4096];
            if(!fgets(read, 4096, stdin)) break;
            int bytes = send(socket_peer, read, strlen(read), 0);
            printf("send %d bytes\n", bytes);
        }
    }
    puts("Closing socket");
    CLOSESOCKET(socket_peer);
    return 0;
}
Recommended Posts