Un Telnet écrit avec la bibliothèque gnet
http://gtermix.sourceforge.net/download.html
Regarde notamment le fichier telnet.c, il y est question de la négociation.
Version imprimable
Un Telnet écrit avec la bibliothèque gnet
http://gtermix.sourceforge.net/download.html
Regarde notamment le fichier telnet.c, il y est question de la négociation.
oui, et je savais à l'avance qu'il serait apprécié; nan, sans dek' je ne le ferai plus (vous m'êtes trop précieux par vos indications pour que je prenne bêtement le risque que la conversation tourne court, et encore MERCI pour les éclairages que vous me donnez)Citation:
arg' encore un pavé
Oui merci; je disais avant-hier que j'étais en train de m'approprier le code de l'ancien fil de discution qu'avait écrit yartempion, mais en guise d'appropriation, je ne vais que lui piquer les quelques lignes qui entament la négociation, et je vais laisser tomber tout le reste qui me provoque des tas de passages en force à la compil', surtout que je ne sais pas corriger ces erreurs toutes relatives à des pointeurs non "castés" que je ne sait pas rendre propres.Citation:
Regarde notamment le fichier telnet.c, il y est question de la négociation.
(Alors que malgré mon inexpérience, mon code à moi était propre)
Bon aller, je vais voir ce que m'a indiqué Emmanuel, et à une prochaine fois,
David
le lien vers le code en question je l'ai déjà mis, ( http://www.developpez.net/forums/d34...rrerid=208640; ) et je viens d'y enlever tous les malloc, realloc et free, qui ne sont jamais utilisés dans le code que je vois en suivant ton lien; de toute façon, je suppose naïvement que ça ne doit servir que quand on a des gros pavés (!) de mémoire à utiliser; ce n'est pas le cas d'un négociation telnet avec ses trois malheureux caractères qui montent à dix ou douze en cas de sous-option compliquée. Donc je n'ai plus de gamelle sur le free double ou je-ne-sais quoi, mais je me retrouve simplement avec une négociation qui ne s'arrête jamais, ce qui est un simple problème dans la logique d'icelle qui ne va assurément pas être difficile à résoudre; juste du if-then-else bien taillé ou un switch adéquat. c'est tout bon,
à bientôt dès que ça se décante...
David
Encore bonjour les gars du net', bonjour à l'heure où j'écris, ou bonsoir pour l'heure à laquelle je suppose que vous me lirez.
Hier soir j'ai encore un peu bidouillé mon code et il se pose à moi la question suivante que je garde sous la main pour vous tenir en haleine le temps de quelques explications préalables.
J'ai donc enlevé d'icelui [mon code] les calloc, malloc et réalloc qui faisaient semblant de s'occuper de la mémoire et qui faisaient surtout prendre une belle gamelle à mon futur client telnet qui devient de plus en plus beau; et pour l'embellir encore, serait-il possible d'y enlever également les select et autres FDISSET et FDZERO, qui eux font semblant de multiplexer les E-S, alors qu'il n'y en a jamais que deux de chaque : modem et clavier en entrée, et écran plus modem en sortie; donc ce n'est peut-être pas la peine de faire compliqué si on peut faire simple !
À ce sujet d'ailleurs, avant même que le soi-disant multiplexage ne soit mis en place, mon embryon de client telnet entame la négociation avec le serveur en écrivant plusieurs commandes sur le socket, et le retour de la fonction write qui fait ces envois est bien non nul. (mais je pense à l'instant que j'aurais du vérifier si c'était bien 3, qui est le nombre d'octets de ces commandes simples que j'envoie)
Donc ça a l'air de marcher correctement avant même que soit mis en place, et probablement de façon bancale, le multiplexage en question.
Par ailleurs, dans l'exemple de code qui est au bout du lien que m'a envoyé Émmanuel, il n'y a aucune bidouille de ce genre; alors est-ce que je peux virer les select et autres &rd et &wr qui alourdissent mon code peut être sans nécessité absolue ?
Vous remarquerez que ce post d'aujourd'hui est vraiment bien... Pas de code, Pas de lourdeurs, une seule question, -nickel quoi.
David
Plus c'est simple, mieux c'est.
Maintenant, attention à ne pas utiliser des mots 'hors contexte'.
Pas de 'modem' ici. Un socket. C'est tout.
Pas de 'multiplexage', mais une attente sur évènements multiples.
Etant donné que Windows ne sait pas gérer autre chose que les sockets avec select(), je ne pourrais pas te suivre dans l'usage de select().
Personnellement, j'utilise plutôt les threads, ce qui, à mon sens, est plus adapté au code synchrone. En gros, une tâche par fonction bloquante
- clavier ; fgets() ou fgetc()
- socket : recv().
Comme le proramme principal est déjà une tâche (thread), il suffit d'en créer un supplémentaire et le tour est joué.
- Tache principale (main() etc.) :
- attente clavier
- émission de données
- Tache ajoutée :
- attente reception
- affichage des données reçues
Tu as l'air de trouver simple de créer des threads qui pourraient simplifier les choses, mais moi je n'en suis qu'à concevoir un travail monotâche, et je ne sais pas "créer" de threads tel le Merlin enchanteur moyen.
Et en plus j'ai fait une connerie moyenne en voulant nettoyer un peu trop mon code tel le maniaque moyen, et ça ne se connecte plus sur mon propre serveur; j'espère que c'est seulement à cause du firestarter, mais c'est pas sûr, je vérifie... OUF ça remarche; ça ne va pas loin puisque ça bloque juste après le premier ou deuxième envoi de commande au début, mais du moment qu'il cause avec le serveur, ça va bien.
En relisant le mot "firestarter" ci dessus, ça me fait penser que t'as parlé de windows alors que je ne m'en sers plus, c'est sous ubuntu que j'essaye d'initier une session telnet sur un serveur qui me laisserait continuer, alors quelles sont les considérations à prendre en compte dans ce que tu écris ?
à bientôt,
David
mouais, j'ai lu ce que tu m'as envoyé mais j'ai pas envie de me plonger là dedans tant que ce n'est pas pour améliorer quelque chose qui marcherait; donc ça sera une étape ultérieure quand j'aurai vraiment BESOIN que ça marche mieux; or pour l'instant ça ne marche encore pas du tout; alors dis moi simplement si je peux m'en sortir en évacuant tous mes select et ce qui va avec.
Merci,
D.
Bon, j'y retourne voir, mais mon espoir que ça aille un peu plus loin s'évanouit.
bonsoir et merci,
David
[22h35] ben j'ai encore un peu lu sans trop comprendre, mais surtout j'ai vu que dans l'exemple que tu m'as signalé, il n'y avait ni select ni départ de thread.
D.
Encore une petite question pour Émmanuel; ceci est une question concernant ce qui se passera quand ça marchera; est-ce que le fait d'avoir différents threads pour les différentes sources de données changera quoi que ce soit, vu que de toute féçon il n'y a qu'un seul microprocesseur qui se tape tout le boulot ?
Cependant ceci me décide à me refaire une petite lecture :Mais je voudrais ton avis là dessus :Citation:
il ya des exemples pas à pas et détaillés dans mon article...
à bientôt,Citation:
j'ai vu que dans l'exemple que tu m'as signalé, il n'y avait ni select ni départ de thread
David
Bah, visiblement, tu ne sais pas ce que sont les threads... Le but n'est pas de faire du parallélisme, mais de ne pas bloquer le programme à cause d'une attente... Les traitements synchrones libèrent le processeur dès qu'ils passent en attente (fgetc(), fgets(), accept(), connect(), receive())
Si tu as une séquence
ca marche beaucoup moins bien que 2 boucles séparées et indépendantes :Code:
1
2
3
4
5
6
7 do fgets() send() recv() printf() while(1)
Emission
RéceptionCode:
1
2
3
4
5 do fgets() send() while(1)
C'est essentiellement du au fait que dans un terminal, la réception de données en beaucoup plus importante en volume que l'émission de données (en gros 1/10). Si à la moindre commande, on fait une réception, on risque de louper 90% du message (il n'est pas perdu, mais il arrive après la prochaine commande, ce qui est absurde...Code:
1
2
3
4
5 do recv() printf() while(1)
Si on met une boucle de réception quel est le critère pour en sortir ? Il n'y a pas d'autre solution simple que les threads. Chacun sa boucle et affaire réglée.
Au risque de dire une connerie, initialement, les échanges entre telnet client & serveur ne se sont jamais fait avec des threads puisque n'existant pas à l'époque.
Eventuellement il pouvait y avoir des processes avec un échange via shared memory, messages queues et synchro avec semaphores...
Ceci dit je reste sur ma position que c'est une vaste erreur de développer un client telnet alors qu'il y en a plein sur le "marché"...
La solution Unix est d'utiliser des processus (fork() etc.) C'est lourd et compliqué...
voila...Citation:
Eventuellement il pouvait y avoir des processes avec un échange via shared memory, messages queues et synchro avec semaphores
A titre expérimental, ce n'est pas inintéressant. Pour en faire un produit, non, évidemment, surtout que c'est un gruyère bien connu, surtout face à SSH.Citation:
Ceci dit je reste sur ma position que c'est une vaste erreur de développer un client telnet alors qu'il y en a plein sur le "marché"...
Chers messieurs, je vous laisse à vos discussions stratosphériques qui me passent 30 000 pieds au dessus de la tête, et j'ai un petit client telnet terre à terre qui plante tout gentiment au moment d'une demande de sous-négociation de l'option 24, donc tout va très bien puisque c'est une vulgaire "Erreur de segmentation" (mal traduite je trouve) et donc il devrait me suffire de reporter ce qui se passe au niveau des négociations vers celui des SOUS-négociations, et mon client ira encore un peu plus loin vers l'ouverture d'une session avec le serveur.
Pour delete :
"plein sur le marché", peut-être, mais pas mon-mien qui se connecte à une machine A quand je ferai "boulot A" ou à la machine B quand je ferai "boulot B" pour contrôler un deuxième type de calculs, et si je veux bien passer quelques temps à bosser depuis chez moi parfois, ce n'est pas pour le perdre, ce temps, à taper des adresse IP compliquées qui se ressemblent toutes alors que je pourrais être connecté avant même que d'avoir fini de taper.Citation:
c'est une vaste erreur de développer un client telnet alors qu'il y en a plein sur le "marché"
Pour Émmanuel :
bien sûr que c'est ça qui m'intéresse, et j'ai même commencé à coder en C pour résoudre le problème du cavalier d'Euler; maintenant j'en suis à voir un peu ce qui se passe avec le net', et bientôt, mon fils m'aidera à faire quelques premiers pas en html puisqu'il en à appris des rudiments lors d'un stage scientifique cet été où il a fait de l'astronomie et ça.Citation:
A titre pédagogique
Pour tous : (si un des assez nombreux autres lecteurs peut me donner l'information pour ma culture générale, qui manque pourtant cruellement de quelque chose de vraiment général)
J'ai lu dans le man de htonl, htons, ntohl et ntohs, queIl me semble que sous unix on a aussi du MSB, et alors ces quatre fonctions de renversement n'auraient plus lieu d'être; est-ce bien le cas ? (que unix soit en MSB et que ces quatre fonction sont inutiles sous unix)Citation:
Sur les i80x86, l’ordre des octets de l’hôte est LSB [.../...] alors que sur les réseaux, notamment internet, l’ordre est MSB.
à bientôt,
David
Ce n'est pas une question de système mais d'architecture. En x86, les données sont stockées LSB en tête. En 68k/PowerPC, c'est MSB en tête. il y a même d'autre codages sur certaines machines exotiques.
L'important est que le réseau est MSB en tête (c'est la norme pour le bits et pour les bytes).
Afin d'assurer l'interopérabilité entre les différentes machines, il convient de respecter la norme.
Ça y est presque, j'ai vu ma propre invite de login par telnet, YOUPI; alors demain j'essaye de me logger pour de bon et finito ou presque; enfin il sera devenu possible de penser à des améliorations cher Emmanuel.
à bientôt,
D.
Bon, alors en effet je vois bien ma mire de login, et je vais vous la copier pour que vous puissier l'admirer aussi, mais auparavant j'ai plusieurs interrogations; Émmanuel, tu m'as dit que le net était MSB en tête, mais est ce que unix l'est aussi ? (question juste en passant)
Maintenent les choses sérieuses :
Le programme client que j'adapte fait un boucle infinie de lecture sur le socket.
Quand le premier octet qu'il y lit est une amorce de commande telnet (un 255 qu'on symbolise par IAC= Is A Command) il sait que la suite est une commande et il la traite en fonction de la valeur des octets qui arrivent, comme indiqué dans les RFC vers lesquelles delete m'a envoyé le lien.
Mais quand ce n'est pas le cas, c'est que la négociation est finie et j'en suis là; et ceux qui ont déjà utilisé telnet se rappellent peut-être qu'à ce moment là, le serveur envoie l'OS qui le gouverne, "Ubuntu 8.04.1" dans mon cas. Et le premier caractère de cette chaine a déjà été lu puisqu'il a servi pour aiguiller entre le traitement d'une commande de négociation, ou une entame de login.
Mon problème est que je peux très bien accéder à cet entier-caractère, mais qu'il n'est pas possible de le récupérer à la tête de la chaine de caractères à laquelle il appartenait, celle qui donne l'OS; et je suis obligé de jongler pour afficher ce caractère seul, qui est en mémoire, suivi immédiatement et sans saut de ligne, de la chaine étêtée.
Bon ça y est je crois avoir compris ce qui se passe. (c'est beau le direct, mais si je n'étais pas extrêmement bienveillant, ça vous priverait de la mire de login que j'aurais mise pour expliquer) alors la voici :Et ce que je crois avoir compris est que ce qui vient du socket est une sorte de flux, et que quand une valeur y a été lue, elle n'y est plus. Donc dans mon cas il me suffit de reconstituer la chaine de l'OS avec un strcat par exemple.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 [.../...] N° traitement des types de message 255 251 5 valeur de la socket 3 WILL 251 demande de negociation Procedure OPTION_NEGOCIEE, *(mess_nego2+2)=5 5 option inconnue ou non negociee i=0 mess_nego= 255 i=1 mess_nego= 251 i=2 mess_nego= 5 i=3 mess_nego= 0 reponse envoyee: i=0 mess_nego= 255 i=1 mess_nego= 254 i=2 mess_nego= 5 i=3 mess_nego= 0 Stn: retour de NEGO, qui était partie avec "��" bas du if(buffer_RX[0]==255) (255=IAC-Is A Command) NEGO apparemment terminée U [ici le caractère d'aiguillage] Ubuntu 8.04.1 [ici ce caractère + la fin de la chaine où est l'OS] Utest login: ^@^@^@^@ [ici ce caractère en trop au début] Stn: envoi de "guest"+RTN Stn: invite de password : ^@ [ici le dernier caractère du login] Stn: envoi de "guest1"+RTN guest NEGO apparemment terminée [ici pourquoi ça recommence ? ] [.../...]
Mais ça n'explique pas que ce caractère revienne plusieurs fois à la tête de diverses chaines que je lis sur le soclet; à suivre...
Bon, et pour la suite il se mélange d'une façon que je ne pige pas bien et vos remarques seront encore les bienvenues pour m'aider à avancer.
David
:zzz: déjà répondu : http://www.developpez.net/forums/m3608039-59/
Alors tu ne peux rien saisir.Citation:
Maintenent les choses sérieuses :
Le programme client que j'adapte fait un boucle infinie de lecture sur le socket.
Autre question ?
Mal à la tête.Citation:
the pavé
Ben non, moi je vois que ça cause de powerPC, de 68 K et de X-86, mais je ne vois rien à propos de machine unix; et j'ai eu à un moment à ma boite un souci de cet ordre, l'ordre des octets justement, entre des SUN et des SGI.Citation:
déjà répondu
Pour l'instant ça ne me dérage pas puisque je n'en suis qu'à essayer de me logger; par la suite je crois que je pourrai toujours aiguiller ce qui vient du clavier-0 vers le socket et ce qui vient du socket vers mon écran-1; cela semble-t'il envisageable ?Citation:
Alors tu ne peux rien saisir
Et mon programme peut'il s'arrêter sans tuer la connexion, donc le socket... ça me parait peu probable, donc il faudra qu'il continue de tourner et fasse les transferts 0->3 et 3->1.
Je suis déjà un peu plus loin, alors je la fais courte : je n'arrive pas à envoyer mon login au serveur :Citation:
the pavé
Il affiche le username que tu connais bien alors que je crois qu'il est déjà en train de lire sur le socket pour rechercher l'invite de password.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 NEGO apparemment terminée, ou pas encore loggé. (0) Ubuntu 8.04.1 Stn: invite de login : (1) test login: ^@^@^@^@ Ok test login: ^@^@^@^@ Stn: envoi de "guest"+CRLF write_server: FD_ISSET(sock, &wr)=1 write_server: Ok, nb_ecr=7, "guest " Stn: invite de password : (1) ^@ (2) guest david@test:~/Skul1-telnet$
Alors un bout du code qui fait ça est là dessous ;
j'ajoute juste la fonction write_server qui est toute simple :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 printf("NEGO apparemment terminée, ou pas encore loggé.\n\n"); read_server(sock, line, rd); // lecture d'une ligne printf("(%d) %c%s\n", i=0, buffer_RX[0], line); // affichage de celle ci i=1; p=NULL; printf("\nStn: invite de login :\n"); while( (p=strstr(line, "login")) == NULL) { read_server(sock, line, rd); // lecture d'une ligne printf("(%d) %s\n", i, line); // affichage de celle ci i++; } // fin du while. printf(" Ok %s \n", line); // et affichage de la bonne // printf("Stn: envoi de \"%s\"+%s\n", "guest", "CRLF"); sprintf(command, "%s%s", "guest", CRLF); write_server(sock, command, wr); // i=1; p=NULL; printf("\nStn: invite de password :\n"); while( (p=strstr(line, "pass")) == NULL) { read_server(sock, line, rd); // lecture d'une ligne printf("(%d) %s\n", i, line); // affichage de celle ci i++; } // fin du while. printf(" Ok %s \n", line); // et affichage de la bonne // printf("Stn: envoi de \"%s\"+%s\n", "guest1", "RTN"); sprintf(command, "%s%s\n", "guest1\n", RTN); write_server(sock, command, wr);
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 static void write_server(SOCKET sock, char *buffer, fd_set wr) { int fdok, nb_ecr; while(fdok == 0) { fdok=FD_ISSET(sock, &wr); } // printf("write_server: FD_ISSET(sock, &wr)=%d\n", fdok); if( (nb_ecr=send(sock, buffer, strlen(buffer), 0) ) < 0) { perror("send()\n"); exit(errno); } else printf("write_server: Ok, nb_ecr=%d, \"%s\"", nb_ecr, buffer); }
Je ne vois pas ce que tu appelles le code de la réception, mais je mets juste après celui de la négo en edit.J'ajoute enfin ce qui se passe là où j'en suis ;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
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341 // // /* procedure de negociation d'option telnet */ NEGOCIATION(buffer_RX, sock, i) // buffer_RX semble être ce que l'on reçoit { unsigned char *mess_nego, *rep_mess_nego; int socket11, j, k; socket11=sock; j=i; rep_mess_nego=mess_nego=buffer_RX; printf("Debut de nego\n"); printf("valeur de j=%d \n valeur des octets reçus :\n", j); for(k=0; k<j+1; k++) // donc j serait la taille en octets du message, moins un; j=2 si 3 octets printf("octet %d= %d \n", k, *(mess_nego+k)); printf("N° traitement des types de message %d %d %d valeur de la socket %d\n", *mess_nego, *(mess_nego+1), *(mess_nego+2), sock); switch(*(mess_nego+1)) { case 250: // SB printf("SB %d demande de sous negociation\n", *(mess_nego+1)); // // je peux essayer de lire et imprimer la sous option pour laquelle une négociation est demandée, printf("DVA, la sous-négociation demandée est la %d\n", *(mess_nego+2)); // puis la refuser par un 255 252 N°deLoption CONCERNÉE(=24 pour la première) // for(k=0; k<j+1; k++) printf("NEGOCIATION: mess_nego[%d]=%d\n", k, mess_nego[k]); printf("NEGOCIATION: socket11=%d\n", socket11); SOUS_OPTION_NEGOCIEE(mess_nego, socket11); printf("NEGOCIATION: retour de SOUS_OPTION_NEGOCIEE !!!\n"); break; case 251: // WILL printf("WILL %d demande de negociation\n", *(mess_nego+1)); OPTION_NEGOCIEE(mess_nego, socket11); break; case 252: // WON'T printf("WONT %d refus de negociation\n", *(mess_nego+1)); OPTION_NEGOCIEE(mess_nego, socket11); *(rep_mess_nego+1)=254; // DON'T *(rep_mess_nego+2)=32; // 32-Terminal speed write(socket11, rep_mess_nego, 3); printf("Reponse a WONT = %d %d %d\n", *(rep_mess_nego+0), *(rep_mess_nego+1), *(rep_mess_nego+2)); break; case 253: // DO printf("DO %d demande de negociation\n", *(mess_nego+1)); OPTION_NEGOCIEE(mess_nego, socket11); break; case 254: printf("DONT %d refus de negociation\n", *(mess_nego+1)); /* OPTION_NEGOCIEE(mess_nego, socket11); */ *(rep_mess_nego+1)=252; write(socket11, rep_mess_nego, 3); printf("Reponse a DON'T = %d %d %d\n", *(rep_mess_nego+0), *(rep_mess_nego+1), *(rep_mess_nego+2)); break; default: printf("NEGOCIATION: Erreur de traitement sur negociation N° d'option=%d\n", *(mess_nego+1)); break; } } // // /* N° d'option a negocier */ OPTION_NEGOCIEE(mess_nego, socket11) // ici on fait quelques write sur le socket... { struct termios terminal_out; speed_t speed_o, speed_i; int socket12, i, k, j; unsigned char *mess_nego2, *rep_mess_nego; socket12=socket11; mess_nego2=mess_nego; printf("Procedure OPTION_NEGOCIEE, *(mess_nego2+2)=%d\n", *(mess_nego2+2)); switch(*(mess_nego2+2)) { case 1: { printf(" Option ECHO\n"); if(*(mess_nego2+1)==253) // 253=DO { printf("reponse %d %d %d %d\n", *(mess_nego2+0), *(mess_nego2+1)=252, *(mess_nego2+2), *(mess_nego2+3)); i=write(socket11, mess_nego2, 4); } } break; case 3: { printf(" Option GA\n"); if(*(mess_nego2+1)==253) { // 253=DO printf("Reception du WILL pour GA\n"); *(mess_nego2+1)=251; } printf("message envoye %d %d %d\n", *(mess_nego2+0), *(mess_nego2+1), *(mess_nego2+2)); i=write(socket11, mess_nego2, 3); } break; case 24: { printf(" Option Terminal type\n"); printf(" Option Terminal type sens de requet %d %d %d %d\n", *(mess_nego2+0), *(mess_nego2+1), *(mess_nego2+2), *(mess_nego2+3)); *(mess_nego2+1)=251; // 251=WILL i=write(socket11, mess_nego2, 3); printf("Reponse envoyee i= %d, %d %d %d %d\n", i, *(mess_nego2+0), *(mess_nego2+1), *(mess_nego2+2), *(mess_nego2+3)); } break; case 31: { printf("Option NAWS\n"); /*printf("Envoi de la sous option direct\n");*/ if((mess_nego2=realloc(mess_nego2, 10*sizeof(unsigned char)))==NULL) printf("realloc echouee sur SB 31\n"); *(mess_nego2+0)=255; // 255=IAC *(mess_nego2+1)=250; // 250=SB Indicates that what follows is subnegotiation of the indicated option. *(mess_nego2+2)=31; *(mess_nego2+3)=0; *(mess_nego2+4)=80; *(mess_nego2+5)=0; *(mess_nego2+6)=24; *(mess_nego2+7)=255; // 255=IAC *(mess_nego2+8)=240; // 240=SE End of subnegotiation parameters printf("message a envoye %d %d %d %d %d %d %d %d\n", *(mess_nego2+0), *(mess_nego2+1), *(mess_nego2+2), *(mess_nego2+3), *(mess_nego2+4), *(mess_nego2+5), *(mess_nego2+6), *(mess_nego2+7)); i=write(socket11, mess_nego2, 9); printf("Reponse NAWS envoyee\n"); } break; case 32: // quand cette sous-option arrive ça fait tout planter, donc j'essaye un WON'T-252 { // mais ici on ne traite pas une SOUS-opt., mais une OPTION.(mais le WON'T semble ZZZ marcher qd même) printf("Option Terminal speed\n"); printf("Sous option Terminal speed N° 32\n"); printf("Option Terminal speed sens de requet %d\n", *(mess_nego2+2)); // S avec 2 au lieu de 3 -Ok *(rep_mess_nego+0)=255; // 255=IAC *(rep_mess_nego+1)=252; // WON'T *(rep_mess_nego+2)=32; // 32-Terminal speed printf("Option Terminal speed sens requet %d %d %d\n", *(mess_nego2+0), *(mess_nego2+1), *(mess_nego2+2)); // ICICICICI SELECT ISSET // printf("DVA: FD_ISSET(sock, &wr)=%d\n", FD_ISSET(socket11, &wr)); write(socket11, rep_mess_nego, 3); // 3 octets renvoyés. } break; case 33: { printf("Option LFLOW\n"); printf("valeur de j=%d \n valeur des octets reçus: \n", j=strlen(mess_nego)); for(k=0;k<j+1;k++) printf("octet %d= %d \n", k, *(mess_nego2+k)); /*if(*(mess_nego2+1)==253) // 253=DO { if((mess_nego2=realloc(mess_nego2, 6*sizeof(unsigned char)))==NULL) printf(" Erreur fatal reallocation de memoire OPTION_NEGOCIEE N° 33\n"); *(mess_nego2+0)=255; // 255=IAC *(mess_nego2+1)=250; *(mess_nego2+2)=33; *(mess_nego2+3)=3; *(mess_nego2+4)=255; // 255=IAC *(mess_nego2+5)=240; printf("Reponse %d %d %d \n", *(mess_nego2+0), *(mess_nego2+1), *(mess_nego2+2)); i=write(socket12, mess_nego2, 6); printf("Message reponse envoyé %d %d %d %d %d %d \n", *(mess_nego2+0), *(mess_nego2+1), *(mess_nego2+2), *(mess_nego2+3), *(mess_nego2+4), *(mess_nego2+5)); }*/ } break; /*case 36: printf("Option d'environnement\n");*/ /*break;*/ default: { printf("%d option inconnue ou non negociee\n", *(mess_nego2+2)); for(i=0; i<sizeof(mess_nego2); i++) printf(" i=%d mess_nego= %d\n", i, *(mess_nego2+i)); if(*(mess_nego2+1)==251) *(mess_nego2+1)=254; else *(mess_nego2+1)=252; printf("reponse envoyee: \n"); for(i=0; i<sizeof(mess_nego2); i++) printf(" i=%d mess_nego= %d\n", i, *(mess_nego2+i)); write(socket12, mess_nego2, sizeof(mess_nego2)); } break; ////free(mess_nego2); } } // /* Sous option negociee */ SOUS_OPTION_NEGOCIEE(mess_nego, socket11) { int i, j; unsigned char *terminal, *mess_nego3, *rep_mess_nego, *vitesse, DEB_SB, FIN_SB, donnee[4]; struct termios terminal_out; speed_t speed_o, speed_i; mess_nego3=mess_nego; DEB_SB=250; FIN_SB=240; donnee[0]="9"; donnee[1]="6"; donnee[2]="0"; donnee[3]="0"; printf("Procedure SOUS_OPTION_NEGOCIEE sous option a negocier valeur de la SB...\n"); printf("Procedure SOUS_OPTION_NEGOCIEE: mess_nego3[0]=%d\n",mess_nego3[0]); printf("Procedure SOUS_OPTION_NEGOCIEE sous option a negocier valeur de la SB %d\n", *(mess_nego3+2)); switch(*(mess_nego3+2)) { case 24:{ printf("Procedure SOUS_OPTION_NEGOCIEE: dans le case %d du switch(*(mess_nego3+2))\n",*(mess_nego3+2)); /*Recuperation d'info sur le terminal*/ printf(" Sous option Type de terminal actuel=%s\n", terminal=getenv("TERM")); printf(" Sous option Type de terminal actuel; longueur de la chaine terminal=%d\n", strlen(terminal)); printf(" Sous option Type de terminal actuel; sizeof(mess_nego3)=%d\n", sizeof(mess_nego3)); printf(" Sous option Type de terminal actuel; strlen+sizeof=%d\n", i=(strlen(terminal)+sizeof(mess_nego3))); printf("sequence reçue taille du message %d %d %d %d %d %d\n", *(mess_nego3+0), *(mess_nego3+1), *(mess_nego3+2), *(mess_nego3+3), *(mess_nego3+4), *(mess_nego3+5)); if((mess_nego3=realloc(mess_nego3,(i+1)*sizeof(unsigned char)))==NULL) printf("realloc echouee sur SB 24\n"); printf("taille de mess_nego3=%d\n", strlen(mess_nego3)); if((terminal=(char*) calloc(strlen(getenv("TERM")), sizeof(char)))==NULL) printf("Impossible d'allouer la memoire terminal\n"); terminal=getenv("TERM"); printf("terminal=%s\n", terminal); printf(" Mise en majuscules :\n"); for(j=0;j<(strlen(getenv("TERM")));j++) { *(terminal+j)=toupper(*(terminal+j)); printf("%d %c\n", j, *(terminal+j)); } strcat(mess_nego3, terminal); printf("sequence du message modifié %d %d %d %d %d %d \n", *(mess_nego3+0), *(mess_nego3+1), *(mess_nego3+2), *(mess_nego3+3)=0, *(mess_nego3+4), *(mess_nego3+5)); printf("chaine de terminal %s\n", terminal); memmove((mess_nego3+4), terminal, strlen(terminal)+1); printf("sequence reçue modifiee %d %d %d %d %c%c%c%c%c%c %d %d %d\n", *(mess_nego3+0), *(mess_nego3+1), *(mess_nego3+2), *(mess_nego3+3)=0, *(mess_nego3+4), *(mess_nego3+5), *(mess_nego3+6), *(mess_nego3+7), *(mess_nego3+8), *(mess_nego3+9), *(mess_nego3+10)=255, *(mess_nego3+11)=240, *(mess_nego3+12)=0); // 255=IAC i=write(socket11, mess_nego3, 13); printf("nombre de caracteres écrits= %d\n", i); i=write(1, "mess_nego3\n", 13); printf("deuxieme valeur de i=%d\n", i); //// free(mess_nego3); } break; // case 32:{ printf("Sous option Terminal speed\n"); printf("sequence reçue taille du message %d %d %d %d %d %d %d %d\n", *(mess_nego3+0), *(mess_nego3+1), *(mess_nego3+2), *(mess_nego3+3), *(mess_nego3+4), *(mess_nego3+5), *(mess_nego3+6), strlen(mess_nego3)); printf("Recuperation de la vitesse du terminal\n"); // printf("OK icii\n"); *(rep_mess_nego+1)=252; // WON'T *(rep_mess_nego+2)=32; // 32-Terminal speed printf("OK làà\n"); write(socket11, rep_mess_nego, 3); // pas d'autre argument donc seuleument 2 octets renvoyés XXX si, 3. // /* tcgetattr(STDIN_FILENO, &terminal_out); speed_o=cfgetospeed(&terminal_out); */ /*printf("vitesse du terminal en out %d\n", speed_o);*/ /* if((mess_nego3=realloc(mess_nego3,(strlen(mess_nego3)+11)*sizeof(unsigned char)))==NULL) printf("realloc echouee sur SB 32\n"); */ /*printf("modification du *(mess_nego3+3) %d\n", *(mess_nego3+3)=0);*/ /* i=write(1, "mess_nego3\n", 13); */ ////(mess_nego3); } break; // case 33:{ printf("Sous option LFLOW\n"); printf("sequence reçue taille du message %d %d %d %d %d %d\n", *(mess_nego3+0), *(mess_nego3+1), *(mess_nego3+2), *(mess_nego3+3), *(mess_nego3+4), *(mess_nego3+5)); switch(*(mess_nego3+3)) { case 0:{ printf("Dans case 0 mess_nego3+3= %d\n", *(mess_nego3+3)); /**(mess_nego3+3)=2; printf("Réponse %d %d %d %d %d %d\n", *(mess_nego3+0), *(mess_nego3+1), *(mess_nego3+2), *(mess_nego3+3), *(mess_nego3+4), *(mess_nego3+5)); i=write(socket11, mess_nego3, 6);*/ } break; case 3:{ printf("Dans case3 mess_nego3+3= %d\n", *(mess_nego3+3)); /**(mess_nego3+3)=4; printf("Réponse %d %d %d %d %d %d\n", *(mess_nego3+0), *(mess_nego3+1), *(mess_nego3+2), *(mess_nego3+3), *(mess_nego3+4), *(mess_nego3+5)); i=write(socket11, mess_nego3, 6);*/ } break; printf("Réponse %d %d %d %d %d %d\n", *(mess_nego3+0), *(mess_nego3+1), *(mess_nego3+2), *(mess_nego3+3), *(mess_nego3+4), *(mess_nego3+5)); default:printf("Dans default mess_nego3+3= %d\n", *(mess_nego3+3)); break; } } break; // case 36: printf("Sous option environnement\n"); break; // default: printf("Sous option non negociee\n"); break; } } // /*negociation de depart*/ NEGOINIT(sock) { unsigned char mesg_nego[7]; printf("NEGOINIT: demande des negos initiales\n"); // printf("DO ECHO\n"); mesg_nego[0]=255; /*IAC*/ mesg_nego[1]=253; /*DO*/ mesg_nego[2]=1; /*ECHO*/ mesg_nego[3]=0; write(sock, mesg_nego, 3); // printf("DO SUPPRESS GO AHEAD\n"); mesg_nego[0]=255; /*IAC*/ mesg_nego[1]=253; /*DO*/ mesg_nego[2]=3; /*SUPPRESS GO AHEAD*/ write(sock, mesg_nego, 3); // //printf("WILL TERMINAL TYPE\n"); //mesg_nego[0]=255; /*IAC*/ //mesg_nego[1]=251; /*WILL*/ //mesg_nego[2]=24; /*TERMINAL TYPE*/ /*write(sock, mesg_nego, 3);*/ // printf("WILL NAWS\n"); mesg_nego[0]=255; /*IAC*/ mesg_nego[1]=251; /*WILL*/ mesg_nego[2]=31; /*TAILLE TERMINAL NAWS*/ write(sock, mesg_nego, 3); // mesg_nego[0]=255; /*IAC*/ mesg_nego[1]=251; /*WILL*/ mesg_nego[2]=32; /*TERMINAL SPEED*/ /*write(sock, mesg_nego, 3);*/ // mesg_nego[0]=255; /*IAC*/ mesg_nego[1]=251; /*WILL*/ mesg_nego[2]=33; /* REMOTE FLOW CONTROL */ write(sock, mesg_nego, 3); // /*mesg_nego[1]=250; */ // 250=SB Indicates that what follows is subnegotiation of the indicated option. /*mesg_nego[3]=1; */ /*mesg_nego[4]=255; */ // 255=IAC /*mesg_nego[5]=240; */ /*write(sock, mesg_nego, 3); */ // printf("NEGOINIT: fin de la nego. initiale\n"); printf("\n"); }
vois-tu une raison qui pourrait expliquer que le user "guest", que j'ai envoyé sur le socket par send(sock, buffer, strlen(buffer) puisse s'y retrouver un peu après lors d'une lecture par recv(sock, buffer, BUF_SIZE - 1, 0) ?Code:
1
2
3
4
5
6
7
8
9
10
11
12 Ubuntu 8.04.1 Stn: recherche de l'invite de login : test login: ^@^@^@^@ Stn: envoi de guest +"RTN " Stn: invite de password : ^@ guest
Merci encore une fois énormément beaucoup de me donner des pistes,
David
Parceque la phase de login produit un echo local.
La phase password non.
Il va certainement falloir que tu utilises la librairie termios.
Toi t'as l'air d'être un fana des librairies; dans presque tous tes post's il y a un lien vers une librairie quelconque ou elle est simplement mentionnée comme ici. Mais pour cet echo, je dois pouvoir me débrouiller avec une négociation adaptée et qui tombe à pic au moment voulu; je vais donc modifier un peu mon code afin de bien mettre en évidence ceci (qu'il me fait grand plaisir d'apprendre, merci, parce que je n'y aurais probablement pas pensé tout seul avant longtemps) et puis ensuite je vois si je peux contourner le phénomène, et puis s'il n'y a pas moyen je verrai si une négociation avec le serveur à ce moment-là pourrait évacuer ce comportement, et pui en dernier lieu je vois chez termios; mais d'un autre côté c'est un nom qui ne m'est pas inconnu [.../...] en effet, il y a bien du "#include <termios.h>" dans mon code, alors pourrais tu me souffler le nom d'une fonction qui désactive l'echo (si c'est bien à peu près ça qui pose problème) ou me filer un de tes nombreux liens qui tombent bien eux aussi.
merci encore de m'avoir éclairé sur la cause de ce qui me bloque,
David
Il s'agit surtout d'une référence à des fonctions systèmes qui permettent de gérer ta console dans un mode particulier, notamment 'sans echo', ce qui est indispensable mors d'une session Telnet établie (je rappelle qu'un client Telnet est un terminal, que chaque caractère tapé est émis immédiatement, que l'écho est géré en retour immédiat par le serveur (masqué -- mot de passe -- ou non -- normal --) et que c'est lui qui gère les corrections (BS) et la fin de saisie (CR ou LF ou CRLF selon le mode)
man termios pour les détails
J'avais donc raison :mouarf:
Termio utilise une structure qui contient différents paramètres cumulables par des masques. eg : c_cflag &= ~(ECHO|ECHONL|ICANON) etc...
De toute façon tu as été prévenu par Emmanuel & Moi-même que tu allais être confronté au problème du terminal. C'est le plus chiant à gérer
Le plus gros reste à faire.
Euh non, delete, j'espère que ce n'est quand même pas le PLUS GROS qui reste à faire; j'en ai déjà assez ch... comme ça. Enfin ceci dit et pour vous conforter dans vos positions tous les deux (salut Émmanuel), voici un echo de ce que me donne la fin de mon bazar :Est-ce que les FD_ISSET servent à quelque chose d'autre qu'à contrôler ? (je ne crois 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 )Négo terminée. Ubuntu 8.04.1 Stn: recherche de l'invite de login : Stn: FD_ISSET(sock, &rd)=1 test login: ^@^@^@^@����������ė�� (1-ième tentative de lecture de l'invite de login) Stn: envoi de guest+"RTN" Stn: FD_ISSET(sock, &wr)=1 Stn: nb_ec=6 ^@st login: ^@^@^@^@����������ė�� (1-ième tentative de lecture de l'echo du login, nb_lu=2) Stn: invite de password : Stn: FD_ISSET(sock, &rd)=1 guest Password: @^@����������ė�� (1-ième tentative de lecture de l'invite de passwd, nb_lu=17) Stn: envoi de guest1+"RTN" Stn: FD_ISSET(sock, &wr)=1 Stn: nb_ec=7 Stn: envoi de la commande "echo toto"+"RTN" : Stn: FD_ISSET(sock, &wr)=1 Stn: nb_ec=10 Stn: FD_ISSET(sock, &rd)=1 est Password: @^@����������ė�� (1-ième tentative de lecture de la réponse, nb_lu=2) Stn: FD_ISSET(sock, &rd)=1 echo toto word: @^@����������ė�� (2-ième tentative de lecture de la réponse, nb_lu=11) david@test:~/Skul1-telnet$
Émmanuel, su t'as essayé de compiler le code que j'ai posté hier (la négo) le compilo doit te sortir pas mal d'insultes; chez moi il y a ces deux genres de choses (avec gcc):pour la première erreur, comment fait on pour caster quelque chose en un pointeur ? Suffirait-il d'utiliser le & qui passe l'adresse ?Code:
1
2 mtn.c:123: attention : assignment makes pointer from integer without a cast mtn.c:197: attention : passing argument 1 of «strlen» makes pointer from integer without a cast
Et pour la deuxième, ça semble vouloir dire que la fonction (strlen ici, mais d'autres ailleurs dans le code)...donc ça semble vouloir dire que cette fonction attend un pointeur, et donc là aussi, suffirait-il d'un & ?
Enfin dernière chose, selon les fois, et donc selon la vitesse et la disponibilité de ce qu'il y a derrière le socket (c'est ma façon de voir les choses, ne hurles pas Émmanuel, je ne suis qu'un pauvre mécanicien)(la mécanique de la physique, pas celle du cambouis) il me semble donc parfois qu'il va jusqu'à se logger, mais comment garder la main sans faire exit ?
merci de vos réponses qui m'ont fait arriver jusqu'ici,
David
PS comment se fait-il quand même qu'il semble y avoir une certaine rémanence dans les échanges ? Comment faire tout bêtement pour nettoyer d'une fois sur l'autre la ligne que je lis sur le socket ? ligne="" n'est pas autorisé comme en fortran je crois, alors avec strcpy ?
D.
Ca sert à tester un état d'un flux : "is [a stream flag] set ?"
Pas eu le temps...Citation:
Émmanuel, su t'as essayé de compiler le code que j'ai posté hier (la négo) le compilo doit te sortir pas mal d'insultes; chez moi il y a ces deux genres de choses (avec gcc):Code:
1
2 mtn.c:123: attention : assignment makes pointer from integer without a cast mtn.c:197: attention : passing argument 1 of «strlen» makes pointer from integer without a cast
Mauvaise question. Il y a deux vrais bugs :Citation:
pour la première erreur, comment fait on pour caster quelque chose en un pointeur ? Suffirait-il d'utiliser le & qui passe l'adresse ?
1 - Le compilateur signale que tu assignes un entier dans un pointeur, ce qui est un non-sens. Précise tes intentions. (dans ce cas, un cast n'est jamais une solution. Le but est de corriger le code et non de le rendre compilable à tout prix)
2 - Le compilateur signale que tu passes un entier à strlen(), alors qu'il attend l'adresse d'un char. Tu ne confonds pas 'A' et "A" ? ou bien char c avec char c[1] ?
Je suppose que, comme maintes fois évoqué, il faut faire une boucle de réception/affichage et une boucle de saisie/émission séparées dans 2 threads.Citation:
Enfin dernière chose, selon les fois, et donc selon la vitesse et la disponibilité de ce qu'il y a derrière le socket (c'est ma façon de voir les choses, ne hurles pas Émmanuel, je ne suis qu'un pauvre mécanicien)(la mécanique de la physique, pas celle du cambouis) il me semble donc parfois qu'il va jusqu'à se logger, mais comment garder la main sans faire exit ?
Officiellement :Citation:
Comment faire tout bêtement pour nettoyer d'une fois sur l'autre la ligne que je lis sur le socket ? ligne="" n'est pas autorisé comme en fortran je crois, alors avec strcpy ?
à la C-h4ck3rzCode:strcpy(ligne, "");
Code:*ligne = 0;
Maintenant j'en vois la nécessité; et je vais donc me taper ta page POSIX threads que j'ai toujours dans un onglet de mon FF; d'ailleurs, relativement à ma dernière question qui n'a pas eu l'heur de susciter le moindre commentaire [.../... vérification en dessous] (nan, nan, il n'y en a pas, mais en fait la "rémanence" devrait disparaitre si je tourne des threads)Citation:
Je suppose que, comme maintes fois évoqué, il faut faire une boucle de réception/affichage et une boucle de saisie/émission séparées dans 2 threads.
Bon, alors au boulot; petite lecture; (et ça tombe presque bien parce que aujourd'hui au boulot, je n'ai fait que de la m... qui ne m'a rien appris)
Alors à bientôt dès que la mise en place de ces satanés threads le nécessitera.
David
J'ai commencé à bouquiner, et alors si je fais comme tu m'as indiqué :
* Tache principale (main() etc.) :
o attente clavier
o émission de données
* Tache ajoutée :
o attente reception
o affichage des données reçues...
...je me retrouve avec un gros souci pour décider de quand les tâches doivent se donner rendez-vous ou s'attendre l'une-l'autre.
Dans mon cas, ça commence par la fonction monip, qui n'a pour but que de lire ma propre adresse IP dans l'en-tête d'un paquet que me renvoit mon FAI, afin de la passer au client telnet que j'essaie de faire pour qu'il ait une adresse à laquelle se présenter.
Pour l'instant il n'y a aucune saisie clavier mais il y a des données émises; donc la sous-tâche doit-elle faire une boucle infinie de lecture sur le socket, et quand elle a lu quelque chose elle se retrouve avec la tâche principale à laquelle elle donne l'adresse IP.
Puis pendant la négociation, le main enverrait les premieres donnés, qui ne sont pas vraiment de la négociation puisqu'aucun retour n'est considéré, mais plutôt une information de l'autre partie de ses propres impératifs.
Puis RDV avec la sous tâche qui a fini par recevoir des données dans la boucle infinie de lecture où elle était et dont elle ne sort qu'une fois des données reçues.
Le main construit une réponse à ces données et les envoit et nouveau RDV avec la sous tâche de réception une fois que celle-ci a des données à mettre à disposition.
:
On continue le mécanisme, où on a en parallèle à chaque fois un envoi du client vers le serveur (le client est bien à l'initiative de la connexion au début) et une réponse du serveur avant RDV entre le main et sa sous tâche.
Ceci se poursuit tout au long de la négociation, et la fin de celle-ci se manifeste par l'absence de commande en provenance du serveur, ce qui est difficile à détecter. Non, c'est en fait là que le serveur envoie l'indication de l'OS qui le gouverne; donc tant que ce que reçoit la sous tâche de réception est une commande telnet (reconnaissable parce qu'elle commence par IAC-FF en hexa) alors la négociation continue, et dès qu'elle reçoit autre chose, c'est l'OS du serveur et la session peut commencer. (après le RDV comme après chaque réception)
Et pour la poursuite de la session aussi, j'ai une émission par le main, pendant que la sous-tâche attend une réponse, qu'elle affiche ou met à disposition dès réception et nouveau RDV.
Bon, ben si jamais j'arrive à rendre ceci dans du code, ce serait vraiment super et je crois que les "rémanences" que j'ai vues ces derniers temps ne devraient plus avoir lieu.
Merci encore Émmanuel,
David
Pourquoi faire ? Si on fait du multitâche, c'est justement pour éviter ça, sinon autant écrire en lineaire. Mais un terminal Telnet, c'est pas du question/réponse. C'est de l'interactif temps réel.
Tu tapes une touche, le caractère est émis et le terminal renvoi le caractère en echo (ou '*' si on saisie le mot de passe). L'écho est reçu.
Tu tapes BS, le BS part, et il revient immédiatement sous la forme BS espace BS etc.
Toi tu te couches tard et moi je me lève tôt...
Alors faudrait-il mieux que la sous-tâche démarre juste après chaque caractère envoyé et ne se resychronise avec le main qu'aprés le traitement éventuel que celui ci peut avoir à faire ? Mais ceci ça revient dans un certain sens à faire justement du question/réponse.
Mais il n'est pourtant pas possible que la sous-tâche tourne toute seule; elle doit bien à certains moments remettre au main les données qu'elle a reçu.
Bon c'est l'heure de finir de petit-déjeûner puis d'aller bosser.
à bientôt,
David
PS. une petite idée quand même juste avant d'y aller, ne serait on pas dans une configuration proche de celle de l'écrivain (la sous-tâche) et du lecteur (le main) ?
Donc je vais relire avec plus d'attention ce passage de ton article.
D.
PSPS: [à cinq heures]
Re-Bonjour,
tu dispourtant la négociation c'est bien du question/réponse, et quand je serai loggé et qu'il relaiera mes commandes vers le serveur, et me renverra le résultat de ces commandes, ce sera proche également; alors il me semble bien qu'il y ait besoin de sychronisation entre le main et sa sous-tâche ou de RDV entre eux, probablement au moins une fois par échange, voire deux.Citation:
Mais un terminal Telnet, c'est pas du question/réponse. C'est de l'interactif temps réel.
Ce n'est pas bien clair tout ça.
D.
PSPSPS: [jeudi à cinq heures et quart]
Re-Re-Bonjour,
j'ai fini par comprendre la phrase où j'ai cru que tu croyais que je bossais sous windows;Ça voulait dire que c'est toi qui bosse sous windows; j'ai fini par le comprendre en relisant une N-ième fois que select n'allait pas chez Bill. Mais moi de mon côté je m'en débrouille petit à petit, à tel point qu'hier mon programme s'est loggé à mon serveur mais une seule fois, et je n'ai pas pu reproduire.Citation:
Etant donné que Windows ne sait pas gérer autre chose que les sockets avec select(), je ne pourrais pas te suivre dans l'usage de select().
Crois-tu que je doive modifier la négociation pour faire faire au serveur ce qu'ils appellent "old line by line" et qui me permettrait d'envoyer et lire des lignes complètes, ou faut il mieux que j'analyse les caractères reçus un à un et ne les envoie aussi que l'un après l'autre ?
David qui continue d'avancer vers le but
[jeudi six heures et demie] Ça chauffe très fort...
aujourd'hui, il s'est loggé des la première tentative, donc j'ai eu la présence d'esprit (bravo) d'enregistrer tout ce qu'il y avait dans la fenêtre, et outre des informations sur le dialogue que je n'ai pas encore analysées, j'ai eu la preuve qu'il s'était bien loggé hier ;Donc je me suis dit que ça ne se passait qu'une fois après le démarrage de la machine, et j'ai donc redémarré mon PC: et basta :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 line= ssword: : line=Last login: Wed Sep 10 20:50:14 CEST 2008 from AToulouse-152-1-103-231.w81-50.a line=bo.wanadoo.fr on pts/3 0:50:14 CEST 2008 from AToulouse-152-1-103-231.w81-50.a line=Linux test 2.6.24-19-generic #1 SMP Fri Jul 11 23:41:49 UTC 2008 i686 The pr line=ograms included with the Ubuntu system are free software; the exact distributi Stn: envoi de la commande "echo toto"+"CRLF" : Stn: nb_ec=11 on terms for each program are described in the individual files in /usr/share/ (1-ième tentative de lecture de la réponse, nb_lu=79) doc/*/copyright. Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent per (2-ième tentative de lecture de la réponse, nb_lu=79) mitted by applicable law.
Ce n'est pas encore tout à fait clean comme fonctionnement puisqu'il faut rebooter la machine pour que ça marche, mais petit youpi déjà; et alors quelle peut être la fonction qui nécessite un redémarrage pour que ça se re-connecte ? J'ai évidemment vérifié que le serveur telnet n'avait pas été tué par le début de session, mais nmap me dit que le service telnet attend bien du monde sur son port 23, et je peux également me logger par telnet 127.0.0.1 .Code:
1
2
3
4
5
6
7
8
9
10 line= ssword: : line=Last login: Thu Sep 11 17:52:30 CEST 2008 from AToulouse-152-1-40-8.w82-125.abo� line=.wanadoo.fr on pts/3 17:52:30 CEST 2008 from AToulouse-152-1-40-8.w82-125.abo� line=Linux test 2.6.24-19-generic #1 SMP Fri Jul 11 23:41:49 UTC 2008 i686 The pr� line=ograms included with the Ubuntu system are free software; the exact distributi�
Alors qu'est-ce que ça pourrait être et quoi vérifier ?
David