Aller au menu - Aller au contenu

[Plan du site] Vous êtes ici --- > Le Site du Zéro > Les tutoriels > Non-Officiels > Programmation > C > Les sockets > Les sockets entre deux applications > La transmission de flux > Lecture du tutoriel

La transmission de flux

Vous vous apprêtez à lire un tutoriel rédigé par un membre de ce site. Malgré tout le soin que ce membre a pu apporter au tutoriel, nous ne pouvons pas garantir que les informations contenues sur cette page sont exactes à 100%. Merci de garder cela en tête lorsque vous lirez cette page ;o)
Avatar
Auteur : zephyr111
Note : 17 / 20 (8 votes)
Visualisations : 10 363

Plus d'informations Plus d'informations
Dans ce chapitre, nous allons apprendre à transmettre des flux d'octets du serveur au client.
Vous verrez que ce que l'on va apprendre est le coeur d'une communication entre le Client et le Serveur. Pour cela, nous allons devoir découvrir d'autres fonctions :p .
Chapitre précédent Sommaire Chapitre suivant

Transmission d'une chaîne de caractères

Pour pouvoir réaliser une transmission de données, le programme serveur va devoir envoyer des données, et le programme client les recevoir.

Pour cela, nous allons utiliser trois fonctions :
Premièrement, nous allons revenir sur le code source du programme serveur, pour étudier le fonctionnement de la fonction send.


La fonction send



Voici son prototype :

Code : C
1
int send(int socket,char *buffer,int len,int flags);
La fonction est très simple :

Code : C
1
send(sock, buffer, sizeof(buffer), 0);


sizeof(buffer) n'est pas toujours la bonne valeur à mettre pour le troisième paramètre. Par exemple, pour les chaines de caractères, il faut utiliser la fonction strlen pour connaitre la taille de la chaine. De même, pour un tableau, il faut passer en paramètre la taille totale du que prend le tableau (nombre de cases * taille d'une case).


La fonction recv



Maintenant, nous allons nous pencher sur l'application client. Pour pouvoir étudier maintenant la fonction recv.
Cette fonction est aussi simple que la fonction send, et son fonctionnement le même :

Code : C
1
int recv(int socket,char * buffer,int len,int flags)
Nous recevrons les données envoyées comme cela :

Code : C
1
recv(sock, buffer, sizeof(buffer), 0);


Tout comme la fonction send, sizeof(buffer) n'est pas toujours la bonne taille e mettre pour le troisième paramètre. Pour cette fonction il ne faut pas mettre une valeur plus grande que la taille du tableau elle-même. Sinon, on risque de voir le programme planter :p .


La fonction shutdown



Voici le prototype de la dernière fonction : elle servira à fermer la transmission de données entre le serveur et le client.

Code : C
1
int shutdown(int socket,int how);
Nous l'utiliserons ainsi, si l'on se place du côté du serveur :

Code : C
1
shutdown(sock, 2);


Maintenant que nous avons tout, nous allons faire le point et améliorer nos deux applications.


Faisons le point



Nous allons améliorer nos deux applications pour qu'elles se transmettent des données : pour cela, nous allons nous servir des trois fonctions précédemment apprises...

Nous allons du côté serveur envoyer un "bonjour" quand un client se connecte, puis fermer l'application.
Du côté client, nous allons recevoir la chaîne de caractères, et l'afficher à l'écran.

Vous pouvez vous lancer maintenant, ce n'est pas difficile ;) . Je suis même persuadé que vous pouvez le faire :p .

Codons ... ...
... ... ... ...

C'est fini ! Voilà la correction ^^ :

Secret (cliquez pour afficher)

L'application SERVEUR :



Code : C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#if defined (WIN32)
#include <winsock2.h>
#elif defined (linux)
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket(s) close(s)
typedef int SOCKET;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR;
#endif
 
#include <stdio.h>
#include <stdlib.h>
#define PORT 23
 
 
 
int main(void)
{
    #if defined (WIN32)
        WSADATA WSAData;
        int erreur = WSAStartup(MAKEWORD(2,0), &WSAData);
    #else
        int erreur = 0;
    #endif
 
    SOCKET sock;
    SOCKADDR_IN sin;
    SOCKET csock;
    SOCKADDR_IN csin;
    char buffer[32] = "Bonjour !";
    int recsize = (int) sizeof csin;
    int sock_err;
 
    /* Si les sockets Windows fonctionnent */
    if(!erreur)
    {
        sock = socket(AF_INET, SOCK_STREAM, 0);
 
        /* Si la socket est valide */
        if(sock != INVALID_SOCKET)
        {
            printf("La socket %d est maintenant ouverte en mode TCP/IP\n", sock);
 
            /* Configuration */
            sin.sin_addr.s_addr    = htonl(INADDR_ANY);   /* Adresse IP automatique */
            sin.sin_family         = AF_INET;             /* Protocole familial (IP) */
            sin.sin_port           = htons(PORT);         /* Listage du port */
            sock_err = bind(sock, (SOCKADDR *) &sin, sizeof sin);
 
            /* Si la socket fonctionne */
            if(sock_err != SOCKET_ERROR)
            {
                /* Démarrage du listage (mode server) */
                sock_err = listen(sock, 5);
                printf("Listage du port %d...\n", PORT);
 
                /* Si la socket fonctionne */
                if(sock_err != SOCKET_ERROR)
                {
                    /* Attente pendant laquelle le client se connecte */
                    printf("Patientez pendant que le client se connecte sur le port %d...\n", PORT);        
 
                    csock = accept(sock, (SOCKADDR *) &csin, &recsize);
                    printf("Un client se connecte avec la socket %d de %s:%d\n", csock, inet_ntoa(csin.sin_addr), htons(csin.sin_port));
 
                    sock_err = send(csock, buffer, 32, 0);
 
                    if(sock_err != SOCKET_ERROR)
                        printf("Chaine envoyée : %s\n", buffer);
                    else
                        printf("Erreur de transmission\n");
 
                    /* Il ne faut pas oublier de fermer la connexion (fermée dans les deux sens) */
                    shutdown(csock, 2);
                }
            }
 
            /* Fermeture de la socket */
            printf("Fermeture de la socket...\n");
            closesocket(sock);
            printf("Fermeture du serveur terminee\n");
        }
 
        #if defined (WIN32)
            WSACleanup();
        #endif
    }
 
    /* On attend que l'utilisateur tape sur une touche, puis on ferme */
    getchar();
 
    return EXIT_SUCCESS;
}


L'application CLIENT



Code : C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#if defined (WIN32)
#include <winsock2.h>
#elif defined (linux)
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket(s) close(s)
typedef int SOCKET;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR;
#endif
 
#include <stdio.h>
#include <stdlib.h>
#define PORT 23
 
 
 
int main(void)
{
    #if defined (WIN32)
        WSADATA WSAData;
        int erreur = WSAStartup(MAKEWORD(2,0), &WSAData);
    #else
        int erreur = 0;
    #endif
 
    SOCKET sock;
    SOCKADDR_IN sin;
    char buffer[32] = "";
 
    /* Si les sockets Windows fonctionnent */
    if(!erreur)
    {
        /* Création de la socket */
        sock = socket(AF_INET, SOCK_STREAM, 0);
 
        /* Configuration de la connexion */
        sin.sin_addr.s_addr = inet_addr("127.0.0.1");
        sin.sin_family = AF_INET;
        sin.sin_port = htons(PORT);
 
        /* Si l'on a réussi à se connecter */
        if(connect(sock, (SOCKADDR *)&sin, sizeof(sin)) != SOCKET_ERROR)
        {
            printf("Connection à %s sur le port %d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
            
            /* Si l'on reçoit des informations : on les affiche à l'écran */
            if(recv(sock, buffer, 32, 0) != SOCKET_ERROR)
                printf("Recu : %s\n", buffer);
        }
        /* sinon, on affiche "Impossible de se connecter" */
        else
        {
            printf("Impossible de se connecter\n");
        }
 
        /* On ferme la socket */
        closesocket(sock);
 
        #if defined (WIN32)
            WSACleanup();
        #endif
    }
 
    /* On attend que l'utilisateur tape sur une touche, puis on ferme */
    getchar();
 
    return EXIT_SUCCESS;
}


Sachez que vous pouvez créer un fichier header.h qui contient les inclusions, typedef et déclarations. Je ne l'ai pas fait pour éviter de vous perdre, avec les fichiers (déjà pas facile, les sockets... avec deux applications :p ). C'est en temps normal vivement recommandé ^^ .

Ce chapitre est la base de la transmission de flux du serveur au client. Il est essentiel, mais assez simple ^^ .
Vous devriez comprendre un peu comment fonctionnent des langages comme le PHP, maintenant ^^ .
Chapitre précédent Sommaire Chapitre suivant
Retour en haut Retour en haut


Créé : le 03/03/2007 à 15:49:16
Modifié : le 22/08/2008 à 15:50:48
Avancement : 100%
Licence : Copie non autorisée

16 commentaires

Changer de design | En savoir plus | Plan du site | Politique d'accessibilité | Règles | RSS tutoriels | RSS news
Édité par Simple IT SARL : Nous contacter | Notre blog | Revue de presse | Publicité

Y'a plus rien à lire, faut remonter maintenant !

Hébergement web - Correction de tutoriels - Créer un site
Vous souhaitez apparaître ici ? Contactez-nous.

Nombre de connectés 133 Zéros connectés | Requêtes SQL 8 requêtes | Temps de génération de la page : Total (SQL) 1.8911s (1.8805s)