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 getaddrinfo
Cette 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