Mode non connecte en C++
Sommaire
- 1 – Schéma d’une relation client-serveur
- 2 – Initialisation de la socket
- 3 – Ecoute du port UDP
- 4 – Echange des données
- 5 – Libération de la socket
- 6 – Exemple complet d’une communication client serveur
- 8 – Les vidéos
- 9 – Suivi du document
- 10 – Discussion autour du mode non connecte en C++
- Commentaire et discussion
- Laisser un commentaire
1 – Schéma d’une relation client-serveur
Voici le schéma d’une relation mode non-connecté entre un client et un serveur.
2 – Initialisation de la socket
Une socket est un mécanisme de couche 5 permettant une communication réseau inter application. En résumé, elle permet la communication entre deux applications situés sur deux machines distinctes.
2.1 Commande WSAStartup()
Windows se basant sur Winsock, nous devons initialiser cette API contrairement à Linux. Pour cela, nous allons utiliser la fonction WSAStartup(). L’utilisation de cette fonction est donc obligatoire pour un système d’exploitation Windows. Si vous utilisez un autre OS, alors passez directement à l’étape suivante. Voici un exemple d’utilisation pour le côté client et serveur.
// ******************************************************** // Déclaration des variables // ******************************************************** WSADATA initialisation_win32; // Variable permettant de récupérer la structure d'information sur l'initialisation int erreur; // Variable permettant de récupérer la valeur de retour des fonctions utilisées // ******************************************************** // Initialisation de Winsock // ******************************************************** erreur=WSAStartup(MAKEWORD(2,2),&initialisation_win32); if (erreur!=0) printf("\nDesole, je ne peux pas initialiser Winsock du a l'erreur : %d %d",erreur,WSAGetLastError()); else printf("\nWSAStartup : OK");
- Le premier paramètre indique la version de Winsock que nous demandons.
- Le second paramètre est l’adresse d’une structure de type WSADATA qui contient toutes les informations nécessaires résultant de l’initialisation.
- La fonction devra renvoyer 0 pour indiquer que sont exécution c’est correctement déroulée.
2.2 – Commande socket()
La création d’une socket est obligatoire afin d’obtenir un identifiant unique. Cela permettra aux prochaines fonctions de toutes ce référencer au même id, donc à la même socket. Voici un exemple d’utilisation pour le côté client et serveur.
// ********************************************************
// Déclaration des variables
// ********************************************************
SOCKET id_de_la_socket; // Identifiant de la socket
// ********************************************************
// Ouverture d'une Socket
// ********************************************************
id_de_la_socket=socket(AF_INET,SOCK_DGRAM,0);
if (id_de_la_socket==INVALID_SOCKET)
printf("\nDesole, je ne peux pas creer la socket du a l'erreur : %d",WSAGetLastError());
else
printf("\nsocket : OK");
- Le premier paramètre indique que vous désirez crée une socket basé sur le protocole IPv4.
- Le second paramètre sélectionne le mode connecté via UDP, cela nécessitera alors une ouverture de session.
- La fonction retournera l’identifiant de la socket si elle s’est exécutée correctement. Sinon, elle indiquera la valeur INVALID_SOCKET.
3 – Ecoute du port UDP
3.1 – Commande bind()
La commande bind permet de lier la socket à un port et adresse IP d’écoute. Voici un exemple d’utilisation pour le côté serveur.
// ******************************************************** // Déclaration des variables // ******************************************************** SOCKADDR_IN information_sur_la_source; // Déclaration de la structure des informations lié à l'écoute // ******************************************************** // Lie la socket à une ip et un port d'écoute // ******************************************************** information_sur_la_source.sin_family=AF_INET; information_sur_la_source.sin_addr.s_addr=INADDR_ANY; // Ecoute sur toutes les IP locales information_sur_la_source.sin_port=htons(33333); // Ecoute sur le port 33333 erreur=bind(id_de_la_socket,(struct sockaddr*)&information_sur_la_source,sizeof(information_sur_la_source)); if (erreur!=0) printf("\nDesole, je ne peux pas ecouter ce port : %d %d",erreur,WSAGetLastError()); else printf("\nbind : OK");
- Le premier argument est l’identifiant de la socket que vous avez récupéré grâce à la fonction socket().
- Le second argument est la structure comprenant les informations sur le port et l’adresse IP à se lier.
- Le troisième paramètre spécifie uniquement la taille de la structure du second.
- La fonction devra renvoyer 0 pour indiquer que sont exécution c’est correctement déroulée.
4 – Echange des données
4.1 – Commande sendto()
La commande sendto permet l’envoi d’une chaîne de caractère à destination du serveur précisé comme argument de la fonction. Voici un exemple d’utilisation pour le côté client.
// ******************************************************** // Déclaration des variables // ******************************************************** int nombre_de_caractere; // Indique le nombre de caractères qui a été reçu ou envoyé char buffer[65535]; // Tampon contenant les données reçues ou envoyées // ******************************************************** // Envoi des données // ******************************************************** information_sur_la_destination.sin_family=AF_INET; // Indiquez l'utilisation d'IPV4 information_sur_la_destination.sin_addr.s_addr=inet_addr("10.10.10.10"); // Indiquez l'adresse IP de votre serveur information_sur_la_destination.sin_port=htons(33333); // Port TCP 33333 à destination du serveur strcpy(buffer,"Coucou, je suis les donnees. www.frameip.com"); // Copie la chaine de caractère dans buffer nombre_de_caractere=sendto(id_de_la_socket,buffer,strlen(buffer),0,(struct sockaddr*)&information_sur_la_destination,sizeof(information_sur_la_destination)); if (nombre_de_caractere==SOCKET_ERROR) printf("\nDesole, je ne peux pas envoyer les donnees du a l'erreur : %d",WSAGetLastError()); else printf("\nsend : OK");
- Le premier argument est l’identifiant de la socket que vous avez récupéré grâce à la fonction socket().
- Le second argument est le buffer contenant les données à envoyer.
- Le troisième paramètre spécifie uniquement la taille du buffer.
- Le quatrième fait référence à la structure comprenant les informations sur le port et l’adresse IP de destination.
- Le cinquième indique la taille de la structure précédente.
- La fonction renverra le nombre de caractère qui a été émis.
4.2 – Commande recvfrom()
La commande recvfrom permet de recueillir dans un buffer les données reçues sur une socket. Voici un exemple d’utilisation pour le côté serveur.
// ******************************************************** // Reception des données // ******************************************************** tempo=sizeof(information_sur_la_source); // Passe par une variable afin d'utiliser un pointeur nombre_de_caractere=recvfrom(id_de_la_socket,buffer,1515,0,(struct sockaddr*)&information_sur_la_source,&tempo); buffer[nombre_de_caractere]=0; // Permet de fermer le tableau après le contenu des data, car la fonction recvfrom ne le fait pas printf("\nVoici les donnees : %s",buffer);
- Le premier argument est l’identifiant de la socket que vous avez récupéré grâce à la fonction accept().
- Le second argument est le buffer contenant les données à recevoir.
- Le troisième paramètre représente le nombre maximum de caractère attendu.
- Le quatrième fait référence à la structure comprenant les informations sur le port et l’adresse IP en écoute.
- Le cinquième indique la taille de la structure précédente.
- La fonction renverra le nombre de caractère qui a été reçu.
5 – Libération de la socket
5.1 Commande closesocket()
Cette fonction permet de libérer proprement l’accès à la socket. Durement conseillé pour le respect d’un développement propre et d’une utilisation saine du système d’exploitation. Voici un exemple d’utilisation pour le côté client et serveur.
// ******************************************************** // Fermeture de la socket correspondant à la commande socket() // ******************************************************** erreur=closesocket(id_de_la_socket); if (erreur!=0) printf("\nDesole, je ne peux pas liberer la socket du a l'erreur : %d %d",erreur,WSAGetLastError()); else printf("\nclosesocket : OK");
- Le premier argument est l’identifiant de la socket que vous avez récupéré grâce à la fonction socket().
- La fonction devra renvoyer 0 pour indiquer que sont exécution c’est correctement déroulée.
5.2 Commande WSACleanup()
Cette étape n’est utile et fonctionnelle que dans le cadres du système d’exploitation Microsoft. Cette fonction permet de libérer l’accès à Winsock. Attention, dans un environnement multiprocess, l’utilisation de cette commande fermera les accès de tous les process. Voici un exemple d’utilisation pour le côté client et serveur.
// ******************************************************** // Quitte proprement le winsock ouvert avec la commande WSAStartup // ******************************************************** erreur=WSACleanup(); // A appeler autant de fois qu'il a été ouvert. if (erreur!=0) printf("\nDesole, je ne peux pas liberer winsock du a l'erreur : %d %d",erreur,WSAGetLastError()); else printf("\nWSACleanup : OK");
- La fonction devra renvoyer 0 pour indiquer que sont exécution c’est correctement déroulée.
6 – Exemple complet d’une communication client serveur
6.1 – Côté serveur
Voici un exemple de code fonctionnel qui permet d’écouter sur le port UDP 33333 et d’afficher les données reçues. Le fichier cpp est disponible ici.
// ******************************************************** // Les includes // ******************************************************** #include <winsock2.h> // pour les fonctions socket #include <cstdio> // Pour les Sprintf // ******************************************************** // Les librairies // ******************************************************** #pragma comment(lib,"ws2_32.lib") // ******************************************************** // Définition des variables // ******************************************************** WSADATA initialisation_win32; // Variable permettant de récupérer la structure d'information sur l'initialisation int erreur; // Variable permettant de récupérer la valeur de retour des fonctions utilisées int tempo; // Variable temporaire de type int int nombre_de_caractere; // Indique le nombre de caractères qui a été reçu ou envoyé char buffer[65535]; // Tampon contenant les données reçues ou envoyées SOCKET id_de_la_socket; // Identifiant de la socket SOCKADDR_IN information_sur_la_source; // Déclaration de la structure des informations lié à l'écoute int main (int argc, char* argv[]) { printf("\nBonjour, vous etes du cote serveur. www.frameip.com\n"); // ******************************************************** // Initialisation de Winsock // ******************************************************** erreur=WSAStartup(MAKEWORD(2,2),&initialisation_win32); if (erreur!=0) printf("\nDesole, je ne peux pas initialiser Winsock du a l'erreur : %d %d",erreur,WSAGetLastError()); else printf("\nWSAStartup : OK"); // ******************************************************** // Ouverture d'une Socket // ******************************************************** id_de_la_socket=socket(AF_INET,SOCK_DGRAM,0); if (id_de_la_socket==INVALID_SOCKET) printf("\nDesole, je ne peux pas creer la socket du a l'erreur : %d",WSAGetLastError()); else printf("\nsocket : OK"); // ******************************************************** // Lie la socket à une ip et un port d'écoute // ******************************************************** information_sur_la_source.sin_family=AF_INET; information_sur_la_source.sin_addr.s_addr=INADDR_ANY; // Ecoute sur toutes les IP locales information_sur_la_source.sin_port=htons(33333); // Ecoute sur le port 33333 erreur=bind(id_de_la_socket,(struct sockaddr*)&information_sur_la_source,sizeof(information_sur_la_source)); if (erreur!=0) printf("\nDesole, je ne peux pas ecouter ce port : %d %d",erreur,WSAGetLastError()); else printf("\nbind : OK"); // ******************************************************** // Reception des données // ******************************************************** tempo=sizeof(information_sur_la_source); // Passe par une variable afin d'utiliser un pointeur nombre_de_caractere=recvfrom(id_de_la_socket,buffer,1515,0,(struct sockaddr*)&information_sur_la_source,&tempo); buffer[nombre_de_caractere]=0; // Permet de fermer le tableau après le contenu des data, car la fonction recvfrom ne le fait pas printf("\nVoici les donnees : %s",buffer); // ******************************************************** // Fermeture de la socket correspondante à la commande socket() // ******************************************************** erreur=closesocket(id_de_la_socket); if (erreur!=0) printf("\nDesole, je ne peux pas liberer la socket du a l'erreur : %d %d",erreur,WSAGetLastError()); else printf("\nclosesocket : OK"); // ******************************************************** // Quitte proprement le winsock ouvert avec la commande WSAStartup // ******************************************************** erreur=WSACleanup(); // A appeler autant de fois qu'il a été ouvert. if (erreur!=0) printf("\nDesole, je ne peux pas liberer winsock du a l'erreur : %d %d",erreur,WSAGetLastError()); else printf("\nWSACleanup : OK"); }
6.2 – Côté client
Voici un exemple de code fonctionnel qui permet d’envoyer des données sur le port UDP 33333, n’oubliez pas de changer l’IP de destination pour correspondre à votre serveur. Le fichier cpp est disponible ici.
// ******************************************************** // Les includes // ******************************************************** #include <winsock2.h> // pour les fonctions socket #include <cstdio> // Pour les Sprintf // ******************************************************** // Les librairies // ******************************************************** #pragma comment(lib,"ws2_32.lib") // ******************************************************** // Définition des variables // ******************************************************** WSADATA initialisation_win32; // Variable permettant de récupérer la structure d'information sur l'initialisation int erreur; // Variable permettant de récupérer la valeur de retour des fonctions utilisées int tempo; // Variable temporaire de type int int nombre_de_caractere; // Indique le nombre de caractères qui a été reçu ou envoyé char buffer[65535]; // Tampon contennant les données reçues ou envoyées SOCKET id_de_la_socket; // Identifiant de la socket SOCKADDR_IN information_sur_la_destination; // Déclaration de la structure des informations lié au serveur int main (int argc, char* argv[]) { printf("\nBonjour, vous etes du cote client. www.frameip.com\n"); // ******************************************************** // Initialisation de Winsock // ******************************************************** erreur=WSAStartup(MAKEWORD(2,2),&initialisation_win32); if (erreur!=0) printf("\nDesole, je ne peux pas initialiser Winsock du a l'erreur : %d %d",erreur,WSAGetLastError()); else printf("\nWSAStartup : OK"); // ******************************************************** // Ouverture d'une Socket // ******************************************************** id_de_la_socket=socket(AF_INET,SOCK_DGRAM,0); if (id_de_la_socket==INVALID_SOCKET) printf("\nDesole, je ne peux pas creer la socket du a l'erreur : %d",WSAGetLastError()); else printf("\nsocket : OK"); // ******************************************************** // Envoi des données // ******************************************************** information_sur_la_destination.sin_family=AF_INET; // Indiquez l'utilisation d'IPV4 information_sur_la_destination.sin_addr.s_addr=inet_addr("10.10.10.10"); // Indiquez l'adresse IP de votre serveur information_sur_la_destination.sin_port=htons(33333); // Port TCP 33333 à destination du serveur strcpy(buffer,"Coucou, je suis les donnees. www.frameip.com"); // Copie la chaine de caractère dans buffer nombre_de_caractere=sendto(id_de_la_socket,buffer,strlen(buffer),0,(struct sockaddr*)&information_sur_la_destination,sizeof(information_sur_la_destination)); if (nombre_de_caractere==SOCKET_ERROR) printf("\nDesole, je ne peux pas envoyer les donnees du a l'erreur : %d",WSAGetLastError()); else printf("\nsend : OK"); // ******************************************************** // Fermeture de la socket correspondant à la commande socket() // ******************************************************** erreur=closesocket(id_de_la_socket); if (erreur!=0) printf("\nDesole, je ne peux pas liberer la socket du a l'erreur : %d %d",erreur,WSAGetLastError()); else printf("\nclosesocket : OK"); // ******************************************************** // Quitte proprement le winsock ouvert avec la commande WSAStartup // ******************************************************** erreur=WSACleanup(); // A appeler autant de fois qu'il a été ouvert. if (erreur!=0) printf("\nDesole, je ne peux pas liberer winsock du a l'erreur : %d %d",erreur,WSAGetLastError()); else printf("\nWSACleanup : OK"); }
8 – Les vidéos
8.1 - How to send Data via UDP packets in C#
In this video I am going to show you How to send Data via UDP packets in C# Tutorial this is often used for ddos however it doesn't have much power also doesn't if you are doing it from just your own pc.
8.2 - How To Create a UDP Server in C#
This has been requested by multiple people so I decided to make a quick UDP Server tutorial. It is not the best server and I may re-do this one in the future - it only handles 1 connection and closes after the client disconnects/stops sending information. I was cut off at the end so I had to sum up Port Forwarding really quickly so please forgive my rushed-ness. Also I think the quality may be a smidge iffey but it should be good enough for now.
8.3 - Cours programmation socket - UDP en langage C
Vidéo en Français présentant l'API en langage C de communication par paquet. L'envoi simple. Envoi-réponse, l'exemple d'un service ECHO.
8.4 - C Programming in Linux Tutorial
C Programming in Linux Tutorial using GCC compiler. Tutorial should also be applicable in C/UNIX programming. This video shows how to use the BSD Socket in C/Linux. You should be proficient in C in order to understand how to use the libraries for TCP/IP socket programming under the Linux environment. Also, it is one of the inter-process communication, or IPC.
9 – Suivi du document
Création et suivi de la documentation par _SebF
10 – Discussion autour du mode non connecte en C++
Vous pouvez poser toutes vos questions, faire part de vos remarques et partager vos expériences à propos du mode non connecte en C++. Pour cela, n’hésitez pas à laisser un commentaire ci-dessous :
Commentaire et discussion