Précédent   Forum du club des développeurs et IT Pro > C et C++ > C > Réseau
Réseau Forum d'entraide sur la programmation réseau en C
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 20/11/2012, 15h07   #41
boboss123
Membre éclairé
 
Inscription : septembre 2009
Messages : 989
Détails du profil
Informations forums :
Inscription : septembre 2009
Messages : 989
Points : 344
Points : 344
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 :
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 :
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 :
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,
boboss123 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/11/2012, 15h17   #42
Emmanuel Delahaye
Rédacteur
 
Avatar de Emmanuel Delahaye
 
Inscription : décembre 2003
Messages : 14 505
Détails du profil
Informations personnelles :
Âge : 56
Localisation : France, Paris (Île de France)

Informations forums :
Inscription : décembre 2003
Messages : 14 505
Points : 19 321
Points : 19 321
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

Des infos sur la programmation et le langage C:
http://bien-programmer.blogspot.com/
http://www.bien-programmer.fr/
http://bien-programmer.forum-actif.net/forum.htm
Emmanuel Delahaye est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/11/2012, 15h22   #43
boboss123
Membre éclairé
 
Inscription : septembre 2009
Messages : 989
Détails du profil
Informations forums :
Inscription : septembre 2009
Messages : 989
Points : 344
Points : 344
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 :
1
2
 
SOCKET sock_cli = accept (sock_srv, (struct sockaddr *) &pin, &address_size);
boboss123 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/11/2012, 17h37   #44
boboss123
Membre éclairé
 
Inscription : septembre 2009
Messages : 989
Détails du profil
Informations forums :
Inscription : septembre 2009
Messages : 989
Points : 344
Points : 344
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 :
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;
}
boboss123 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 17h57.


 
 
 
 
Partenaires

Hébergement Web