IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau C Discussion :

un serveur /plusieurs clients


Sujet :

Réseau C

  1. #41
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    Citation Envoyé par Emmanuel Delahaye Voir le message
    Ne pas boucler la fonction de traitement du client. Ici, tu fais de l'évènementiel, pas du multi-tâche...

    Ceci fonctionne sous Windows (j'ai ouvert 3 clients Telnet). Non testé ailleurs, mais c'est censé fonctionner sous Linux. (en remettant un N° de port qui va bien)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
     
    /* Program server */
     
    #ifdef __cplusplus
    #error Be sure you are using a C compiler...
    #endif
     
    #if defined (WIN32) || defined (_WIN32)
     
    #include <winsock2.h>
     
    #elif defined (linux) || defined (_POSIX_VERSION) || defined (_POSIX2_C_VERSION)\
     || defined (_XOPEN_VERSION)
     
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>             /* close */
     
    #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;
     
    #else
    #error not defined for this platform
    #endif
     
    #include <stdio.h>
    #include <stdlib.h>
     
    /* macros ============================================================== */
    /* constants =========================================================== */
     
    /* constante */
    #define port 23
     
    /* types =============================================================== */
    /* structures ========================================================== */
    /* private data ======================================================== */
    /* private functions =================================================== */
     
    static int traiter_client (int sock_cli)
    {
       int err = 0;
       char buf[1024];
     
       int n = recv (sock_cli, buf, sizeof (buf) - 1, 0);
     
       if (n > 0)
       {
          /* process the received data */
          buf[n] = '\0';
     
          printf ("Received %d chars:'%s' on socket %d\n", n, buf, sock_cli);
       }
       else
       {
          if (n == 0)
          {
             printf ("deconnexion socket %d\n", sock_cli);
          }
          else
          {
             printf ("receive error on socket %d\n", sock_cli);
          }
          err = 1;
       }
       return err;
    }
     
    static int get_cli_ndx (SOCKET a[], int n)
    {
       int ndx = -1;
       int i;
       for (i = 0; i < n; i++)
       {
          if (a[i] == INVALID_SOCKET)
          {
             ndx = i;
             break;
          }
       }
       return ndx;
    }
     
    static int server (void)
    {
       /* creation socket */
       SOCKET sock_srv = socket (PF_INET, SOCK_STREAM, 0);
       if (sock_srv == INVALID_SOCKET)
       {
          perror ("call to socket\n");
          exit (EXIT_FAILURE);
       }
       printf ("socket ok\n");
     
       /*initialization */
       struct sockaddr_in sin = { 0 };
     
       sin.sin_family = AF_INET;
       sin.sin_addr.s_addr = INADDR_ANY;
       sin.sin_port = htons (port);
     
        /*BIND*/ if (bind (sock_srv, (struct sockaddr *) &sin, sizeof (sin)) < 0)
       {
          perror ("call to bind\n");
          exit (-1);
       }
       printf ("bind ok\n");
     
       /* setsockopt */
       int bOptVal = 1;
       int bOptLen = sizeof (int);
     
       if (setsockopt
           (sock_srv, SOL_SOCKET, SO_REUSEADDR, (char *) &bOptVal,
            bOptLen) != SO_ERROR)
       {
          printf ("Set reuseaddr: ON\n");
       }
     
       /* LISTEN */
       if (listen (sock_srv, 5) < 0)
       {
          perror ("call to listen\n");
          exit (EXIT_FAILURE);
       }
     
       printf ("waiting for connections...\n");
     
       SOCKET a_cli[] = { INVALID_SOCKET, INVALID_SOCKET, INVALID_SOCKET };
    #define NB_CLI (sizeof a_cli/sizeof *a_cli)
     
       while (1)
       {
          fd_set inputs;
     
          /* compute the 1st parameter of select (ignored with Windows) */
          SOCKET sock_last = sock_srv;
     
          FD_ZERO (&inputs);        /*réinitialisation list of client */
          FD_SET (sock_srv, &inputs); /*set with the server socket (accept) */
     
          /* set clients (recv) */
          {
             size_t i;
     
             for (i = 0; i < NB_CLI; i++)
             {
                SOCKET sock_cli = a_cli[i];
     
                if (sock_cli != INVALID_SOCKET)
                {
                   FD_SET (sock_cli, &inputs);
                   if (sock_last < sock_cli)
                   {
                      sock_last = sock_cli;
                   }
                }
             }
          }
          sock_last++;
     
          /*select on the client list */
          if ((select (sock_last, &inputs, NULL, NULL, NULL)) < 0)
          {
             perror ("select error\n");
          }
          printf ("select()\n");
     
          if (FD_ISSET (sock_srv, &inputs))
          {
             /* accept the connection */
             struct sockaddr_in pin;
             int address_size;
             SOCKET sock_cli =
                accept (sock_srv, (struct sockaddr *) &pin, &address_size);
             if (sock_cli == INVALID_SOCKET)
             {
                perror ("call to accept\n");
                exit (EXIT_FAILURE);
             }
             printf ("A client is connected with socket %d\n", sock_cli);
             FD_SET (sock_cli, &inputs);
             {
                int i = get_cli_ndx (a_cli, NB_CLI);
     
                if (i != -1)
                {
                   a_cli[i] = sock_cli;
                }
                else
                {
                   closesocket (sock_cli);
                }
             }
          }
     
          /* check clients */
          {
             size_t i;
             for (i = 0; i < NB_CLI; i++)
             {
                SOCKET sock_cli = a_cli[i];
     
                if (sock_cli != INVALID_SOCKET)
                {
                   if (FD_ISSET (sock_cli, &inputs))
                   {
                      int err = traiter_client (sock_cli);
     
                      if (err)
                      {
                         closesocket (sock_cli);
                         a_cli[i] = INVALID_SOCKET;
                      }
                   }
                }
             }
          }
       }
     
    /* close clients */
       {
          size_t i;
          for (i = 0; i < NB_CLI; i++)
          {
             SOCKET sock_cli = a_cli[i];
     
             if (sock_cli != INVALID_SOCKET)
             {
                closesocket (sock_cli);
                a_cli[i] = INVALID_SOCKET;
             }
          }
       }
    /* close server */
       closesocket (sock_srv);
       return 0;
    }
     
    /* entry point ========================================================= */
     
    /* ---------------------------------------------------------------------
       --------------------------------------------------------------------- */
    int main (void)
    {
       int ret;
     
    #if defined (WIN32) || defined (_WIN32)
       WSADATA wsa_data;
       int err = WSAStartup (MAKEWORD (2, 2), &wsa_data);
     
       if (!err)
       {
          puts ("WIN: winsock2: OK");
    #else
       int err;
    #endif
     
       server ();
     
    #if defined (WIN32) || defined (_WIN32)
       WSACleanup ();
    }
    #endif
     
    if (err)
    {
       ret = EXIT_FAILURE;
    }
    else
    {
       ret = EXIT_SUCCESS;
    }
     
    return ret;
    }

    Bonjour,
    J'ai copier/coller ce code mais je n'arrive pas à le faire fonctionner.
    IDE : code:block
    OS : Windows XP SP3

    Lorsque je le lance le serveur, ça me marque dans la console :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    WIN: winsock2: OK
    socket ok
    bind ok
    Set reuseaddr: ON
    wainting for connections...
    Ensuite lorsque je me connecte de dessus avec putty (mode Telnet en 127.0.0.1), ça me met :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    select()
    call to accept
    : No error
     
    Process returned 1 (0x1)    execution time : 9.853 s
    Press any key to continue
    => le serveur et putty s'arretent

    D'où peut venir le problème ?

    Merci d'avance,

  2. #42
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Aucune idée, et ça fait 4 ans que je ne pratique plus la programmation ... Désolé. A l'époque, ça fonctionnait avec Telnet ...
    Pas de Wi-Fi à la maison : CPL

  3. #43
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    Citation Envoyé par Emmanuel Delahaye Voir le message
    ça fait 4 ans que je ne pratique plus la programmation
    C'est bien dommage

    Merci quand même.
    Personne d'autre ne voit d'où peut venir le problème (ou a un code de serveur Telnet qui fonctionne ?)

    A priori, c'est cette ligne qui pose problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SOCKET sock_cli = accept (sock_srv, (struct sockaddr *) &pin, &address_size);

  4. #44
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    J'ai réussi à faire un petit serveur telnet qui renvoie les caractères émis par le client.
    Par contre ça ne gère qu'un client et je ne suis pas sure que ça soit très clean le code. Si vous avez des commentaires n'hésitez pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <winsock2.h>
    //#pragma comment(lib, "ws2_32.lib")
     
     
    // ***************************************************
    // Options Telnet :
     
    // Interpret as command  (début de l'option)
    #define TELNET_IAC_VAL  								'\xff'
    #define TELNET_IAC										"\xff"
     
     
    // WILL indique que le terminal veut gérer l'option
    // WONT indique que le terminal ne veut pas gérer l'option
    // DO indique au terminal distant qu'il doit utiliser gérer l'option
    // DONT indique au terminal distant qu'il ne doit pas utiliser gérer l'option
    // => pour les options non reconnues, il suffit de repondre un WONT aux requetes DO
    #define TELNET_WILL										"\xfb"
    #define TELNET_WONT										"\xfc"
    #define TELNET_DO										"\xfd"
    #define TELNET_DONT										"\xfe"
     
    // Options :
    #define TELNET_ECHO 									"\x01"
    #define TELNET_SUPPRESS_GO_AHEAD						"\x03"
    #define TELNET_TERMINAL_TYPE 							"\x18"
    #define TELNET_STATUS 									"\x05"
    #define TELNET_TERMINAL_SPEED 							"\x20"
    #define TELNET_NEW_ENVIRONMENT_OPTION 					"\x27"
    #define TELNET_NAWS						 				"\x1f" // Negotiate About Window Size
    															   // utilisation : IAC SB NAWS WIDTH[1] WIDTH[0] HEIGHT[1] HEIGHT[0] IAC SE
     
     
     
    // Commandes complètes :
    #define TELNET_WILL_ECHO 								TELNET_IAC TELNET_WILL TELNET_ECHO
    #define TELNET_WILL_SUPPRESS_GO_AHEAD					TELNET_IAC TELNET_WILL TELNET_SUPPRESS_GO_AHEAD
    #define TELNET_WILL_TERMINAL_TYPE 						TELNET_IAC TELNET_WILL TELNET_TERMINAL_TYPE
    #define TELNET_WILL_TERMINAL_SPEED 						TELNET_IAC TELNET_WILL TELNET_TERMINAL_SPEED
    #define TELNET_WILL_NEW_ENVIRONMENT_OPTION 				TELNET_IAC TELNET_WILL TELNET_NEW_ENVIRONMENT_OPTION
    #define TELNET_WILL_NAWS 								TELNET_IAC TELNET_WILL TELNET_NAWS
     
    #define TELNET_WONT_ECHO 								TELNET_IAC TELNET_WONT TELNET_ECHO
    #define TELNET_WONT_SUPPRESS_GO_AHEAD					TELNET_IAC TELNET_WONT TELNET_SUPPRESS_GO_AHEAD
    #define TELNET_WONT_TERMINAL_TYPE 						TELNET_IAC TELNET_WONT TELNET_TERMINAL_TYPE
    #define TELNET_WONT_TERMINAL_SPEED 						TELNET_IAC TELNET_WONT TELNET_TERMINAL_SPEED
    #define TELNET_WONT_NEW_ENVIRONMENT_OPTION 				TELNET_IAC TELNET_WONT TELNET_NEW_ENVIRONMENT_OPTION
    #define TELNET_WONT_NAWS 								TELNET_IAC TELNET_WONT TELNET_NAWS
     
    #define TELNET_DO_ECHO 									TELNET_IAC TELNET_DO TELNET_ECHO
    #define TELNET_DO_SUPPRESS_GO_AHEAD						TELNET_IAC TELNET_DO TELNET_SUPPRESS_GO_AHEAD
    #define TELNET_DO_TERMINAL_TYPE 						TELNET_IAC TELNET_DO TELNET_TERMINAL_TYPE
    #define TELNET_DO_STATUS         						TELNET_IAC TELNET_DO TELNET_STATUS
    #define TELNET_DO_TERMINAL_SPEED 						TELNET_IAC TELNET_DO TELNET_TERMINAL_SPEED
    #define TELNET_DO_NEW_ENVIRONMENT_OPTION 				TELNET_IAC TELNET_DO TELNET_NEW_ENVIRONMENT_OPTION
    #define TELNET_DO_NAWS 									TELNET_IAC TELNET_DO TELNET_NAWS
     
    #define TELNET_DONT_ECHO 								TELNET_IAC TELNET_DONT TELNET_ECHO
    #define TELNET_DONT_SUPPRESS_GO_AHEAD					TELNET_IAC TELNET_DONT TELNET_SUPPRESS_GO_AHEAD
    #define TELNET_DONT_TERMINAL_TYPE 						TELNET_IAC TELNET_DONT TELNET_TERMINAL_TYPE
    #define TELNET_DONT_TERMINAL_SPEED 						TELNET_IAC TELNET_DONT TELNET_TERMINAL_SPEED
    #define TELNET_DONT_NEW_ENVIRONMENT_OPTION 				TELNET_IAC TELNET_DONT TELNET_NEW_ENVIRONMENT_OPTION
    #define TELNET_DONT_NAWS 								TELNET_IAC TELNET_DONT TELNET_NAWS
     
     
     
     
    // ***************************************************
    int main(){
     
     
        int iResult, iSendResult;
     
        WSADATA WSAData;
        SOCKET sock;
        SOCKET csock;
        SOCKADDR_IN sin;
        SOCKADDR_IN csin;
        WSAStartup(MAKEWORD(2,0), &WSAData);
        sock = socket(AF_INET, SOCK_STREAM, 0);
        sin.sin_addr.s_addr = INADDR_ANY;
        sin.sin_family = AF_INET;
        sin.sin_port = htons(23);
        bind(sock, (SOCKADDR *)&sin, sizeof(sin));
        listen(sock, 0);
     
     
        // ****************************
        // configuration du client et serveur Telnet
        const char telnet_options[] =
            TELNET_DO_SUPPRESS_GO_AHEAD
            TELNET_WILL_SUPPRESS_GO_AHEAD
            TELNET_DONT_ECHO
            TELNET_WILL_ECHO
            TELNET_DO_NAWS
            TELNET_DO_STATUS
            TELNET_DO_TERMINAL_TYPE
        ;
     
        // ****************************
        // Boucle infinie. Exercice : améliorez ce code.
        printf("Telnet socket opened\n");
     
        while(1){
            while(1){
                int sinsize = sizeof(csin);
                if((csock = accept(sock, (SOCKADDR *)&csin, &sinsize)) != INVALID_SOCKET){
                    printf("Client connected\n");
     
     
                    // envoie la configuration du telnet
                    iSendResult = send(csock, telnet_options, sizeof(telnet_options), 0);
                    if (iSendResult == SOCKET_ERROR) {
                        //printf("send failed: %d\n", WSAGetLastError());
                        closesocket(csock);
                        WSACleanup();
                        return 1;
                    }
                    break;
                }
            }
     
     
            // ****************************
            #define DEFAULT_BUFSIZE 512
     
            char recvbuf[DEFAULT_BUFSIZE];
     
            // Receive until the peer shuts down the connection
            do {
     
                // cette fonction est blocante (tant qu'il n'y a rien de reçu ou une erreur detectée)
                iResult = recv(csock, recvbuf, DEFAULT_BUFSIZE, 0);
     
                if (iResult > 0){
                    printf("Bytes received: %d\n", iResult);
     
                    // On renvoie les caractères reçus
                    // => on ne renvoie pas les données si le buffer contient des options Telnet
                    // => cette methode pour éviter le renvoie des options Telnet est un peu bourrine (pas sure que ça fonctionne dans tous les cas)
                    if(recvbuf[0] != TELNET_IAC_VAL){
                        iSendResult = send(csock, recvbuf, iResult, 0);
                        if (iSendResult == SOCKET_ERROR) {
                            //printf("send failed: %d\n", WSAGetLastError());
                            closesocket(csock);
                            WSACleanup();
                            return 1;
                        }
                    }
                    //printf("Bytes sent: %d\n", iSendResult);
     
     
                } else if (iResult == 0){
                    printf("Connection closing...\n");
                } else {
                    printf("recv failed: %d\n", WSAGetLastError());
                    closesocket(csock);
                    WSACleanup();
                    return 1;
                }
     
            } while (iResult > 0);
        }
     
     
        closesocket(csock);
        WSACleanup();
        return 0;
    }

Discussions similaires

  1. Script serveur , plusieurs clients
    Par youcef81 dans le forum Programmation et administration système
    Réponses: 0
    Dernier message: 06/11/2007, 15h04
  2. Comment faire un serveur hébergeant plusieurs client simultanée
    Par Alexlesilex dans le forum Développement
    Réponses: 15
    Dernier message: 01/03/2007, 14h15
  3. Réponse d'un serveur à plusieurs clients
    Par Reven777 dans le forum C++Builder
    Réponses: 7
    Dernier message: 12/05/2006, 16h00
  4. Réponses: 72
    Dernier message: 05/12/2005, 10h45
  5. Plusieurs clients et un serveur
    Par mzt.insat dans le forum Développement
    Réponses: 2
    Dernier message: 13/10/2005, 15h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo