socket et read
Le
unbewusst.sein
je m'essaie un petit programme envoyant une commande à un serveur de
nouvelles et lisant la réponse, la partie intéressée :
cmd = "LIST NEWSGROUPS";
send(s, cmd, strlen(cmd), 0);
// s est le socket
while ((bytes = read(s, buf, BUFSIZ)) > 0)
write(1, buf, bytes);
// hanging.
fflush(stdout);
fprintf(stdout, "Ready to close connection to news.free.fr");
close(s);
return 0;
apparemment, si j'ai bien compris, ça "hang" avant "flush(stdout);" car
je ne sorts pas de la boucle while.
le serveur lui a pourtant répondu correctement et a terminé par une
ligne avec simplement un point "." :
alt.irc.dalnet The DALnet IRC network.
.
^C
et je suis obligé d'arrêter par ctrl C.
donc, j'imagine que je dois rompre la boucle while si la ligne contient
bien cet unique caractère (avec CRLF?).
du coup je me pose la question de savoir que fait exactement read ?
(sur mac os x le man n'en dit pas grand chose si ce n'est que c'est une
commande 'buitin')
ça lit une ligne ? (ce que je suppose)
en fait si je teste buf à '.' ça coupe trop vite la connection :
while ((bytes = read(s, buf, BUFSIZ)) > 0 && *buf != '.')
write(1, buf, bytes);
fflush(stdout);
fprintf(stderr, "Ready to close connection to news.free.fr");
la dernière ligne au terminal étant :
altReady to close connection to news.free.fr
^ un "." et la suite
manquent.
ça signifie que ma comparaison :
*buf != '.'
n'est pas bonne
que je dois comparer le premier caractère de buf à . et le suivant à
?
comment faire ?
mon buf est déclaré ainsi :
char buf[BUFSIZ+1];
--
« La vie ne se comprend que par un retour en arrière,
mais on ne la vit qu'en avant. »
(Sören Kierkegaard)
nouvelles et lisant la réponse, la partie intéressée :
cmd = "LIST NEWSGROUPS";
send(s, cmd, strlen(cmd), 0);
// s est le socket
while ((bytes = read(s, buf, BUFSIZ)) > 0)
write(1, buf, bytes);
// hanging.
fflush(stdout);
fprintf(stdout, "Ready to close connection to news.free.fr");
close(s);
return 0;
apparemment, si j'ai bien compris, ça "hang" avant "flush(stdout);" car
je ne sorts pas de la boucle while.
le serveur lui a pourtant répondu correctement et a terminé par une
ligne avec simplement un point "." :
alt.irc.dalnet The DALnet IRC network.
.
^C
et je suis obligé d'arrêter par ctrl C.
donc, j'imagine que je dois rompre la boucle while si la ligne contient
bien cet unique caractère (avec CRLF?).
du coup je me pose la question de savoir que fait exactement read ?
(sur mac os x le man n'en dit pas grand chose si ce n'est que c'est une
commande 'buitin')
ça lit une ligne ? (ce que je suppose)
en fait si je teste buf à '.' ça coupe trop vite la connection :
while ((bytes = read(s, buf, BUFSIZ)) > 0 && *buf != '.')
write(1, buf, bytes);
fflush(stdout);
fprintf(stderr, "Ready to close connection to news.free.fr");
la dernière ligne au terminal étant :
altReady to close connection to news.free.fr
^ un "." et la suite
manquent.
ça signifie que ma comparaison :
*buf != '.'
n'est pas bonne
que je dois comparer le premier caractère de buf à . et le suivant à
?
comment faire ?
mon buf est déclaré ainsi :
char buf[BUFSIZ+1];
--
« La vie ne se comprend que par un retour en arrière,
mais on ne la vit qu'en avant. »
(Sören Kierkegaard)

Poser une question


finalement j'ai changé mon code pour :
while ((bytes = read(s, buf, BUFSIZ)) > 0) {
if(*buf == '.' && buf[1] == 'n') {
break;
}
write(1, buf, bytes);
}
et ça hang toujours là je pense que le "caractère" (à supposé qu'il n'y
en ait qu'un) de fin de ligne, n'est pas 'n'.
--
« La vie ne se comprend que par un retour en arrière,
mais on ne la vit qu'en avant. »
(Sören Kierkegaard)
Normal. Tu fais beaucoup trop de suppositions. Si tu veux programmer en
réseau en C, il faut que tu lises un livre de base : "Internetworking
with TCP/IP".
L'appel système read est par défaut bloquant. Il retourne 0 sur
déconnexion du distant. Pour éviter d'être bloqué on effectue
généralement un select avant l'appel système. Read ne connaît pas la
notion de ligne, il lit un flux de données et retourne les octets qu'il
a réussi à lire. Tester le premier mot du buffer ne teste pas le premier
mot d'une ligne, sauf hasard.
Tout est dans le bouquin. Bonne lecture.
--
Éric Lévénez
FAQ de fclc :
C'est pourri ca. Tu mélange les écriture sur write() et sur stdout. Il
ne faut pas faire ainsi. stdout a un buffer que tu bypass en utilisant
un write(1, ...). Il ne faut pas s'etonner si tu vois des trucs affichés
dans le mauvais ordre en procédant ainsi.
sois homogène dans tes API => utilise fwrite plutot.
non. Ca lit au plus le nombre d'élements passés en argument ou jusqu'à
la fin de fichier. Ca peut donc lire une ligne, mais 2 lignes ou plus
aussi. Ca dépend. Ca peut aussi en lire moins (le début d'une ligne ou
pas). Ca depend de comment la couche reseau en dessous découple les
elements. (je connais des couches reseau qui découpent tout en 64bits,
donc on obtient jammais une ligne de 80 car d'un coup).
C'est mieux.
C'est normal... regarde ton while(). Il lit le '.' mais ne l'imprime pas.
Sisi.. c'est juste que tu oublie d'imprimer le '.' que tu viens de lire.
while((bytes = read(s, buff, BUFSIZ)) > 0) {
fwrite(buf, sizeof(*buf), BUFSIZ, stdout);
if(*buf == '.') break;
}
sam.
(En supposant que tu discutes avec un serveur nntp:) le protocole
spécifie que la fin de liste est '.', 'r', 'n' (point, CR, LF).
La boucle ne risque donc pas d'être cassée.
De plus, rien ne garantit que le '.' arrivera en 1ere position, ça
dépend du serveur, de tcp, du système utilisé, etc.
Si tu veux lire par ligne, tu peux utiliser fdopen(3) et fgets(3)
sur la sockette.
Sisi.
--
christophe.
oui, c'est bien ce qui se passe.
--
« La vie ne se comprend que par un retour en arrière,
mais on ne la vit qu'en avant. »
(Sören Kierkegaard)