OVH Cloud OVH Cloud

socket et read

15 réponses
Avatar
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\n";
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\n");

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\n");

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 à \n
?

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)

5 réponses

1 2
Avatar
xtof.pernod
Le 14/06/2010 00:22, Marc Espie a fait rien qu'à écrire :
In article <1jk1al1.jxcmerfl3g1bN%,
Une Bévue wrote:
[...] >> // s est le socket -> serveur nntp


(...)

Une autre possibilite consiste a utiliser fdopen et laisser faire la
bibliotheque standard. Seul risque de cette possibilite: cela condamne une
utilisation ulterieure de la socket en mode non-bloquant (ben oui, aucune
garantie que stdio fonctionne avec des fd en non bloquant).



Pas trop grave, comme condamnation.. Si tu pars avec fdopen(3) et autres
fgets(), en général, tu fais tout le prog. avec.

Si tu veux gérer toi-même les dépassements de délai, laisser le fd en
mode bloquant / comportement par défault, un coup de signal(3) avec
SIGALRM, et alarm(3) et le tour est joué.

(Note. Je dis pas que c'est une bonne méthode, mais c'est assez simple..)

je ne saurais trop te conseiller de te procurer un peu de litterature,
comme le "network programming " de Stevens...



... avant de poster sauvagement au 1er bug ?! =) ...

--
christophe.
Avatar
unbewusst.sein
Samuel DEVULDER wrote:

Comme c'est fastidieux, tu peux convertir ta socket en FILE* avec
fdopen(3) et lire dessus avec un bon fgets() des familles. Fais
attention cependant à avoir un buffer suffisamment grand ou sinon tu ne
va ne lire qu'une partie de la ligne courante et tu va te désynchroniser
avec le serveur.



oui, merci, ça j'ai fait, je ne connaissais pas cette "astuce".
c'est christophe, plus haut dans le fil qui me l'a donnée.

L'idéal serait que tu te fasse une routine avec fgetc() et realloc()
pour lire une ligne "quelle que soit sa longueur". Sans vérif ca
ressemblerait à ceci

// lecture dynamique d'une ligne jusqu'au n final les 'r' sont
// ignores.
char *getLine(FILE *f) {
// buffer
const int CHUNK_SIZE = 1024;
int bufsize = CHUNK_SIZE;
char *buf = malloc(buffsize);

// position du prochain caractère à écrire
int pos = 0;

if(buf==NULL) {...erreur out of mem...}

while(1) {
int c = fgetc(f);
if(c=='n' || c==EOF) break;
if(c!='r') {
// on ajoute le caractère au buffer
buf[pos++] = c;
// plus de place pour le caractere suivant
// (ou le final): on realloue
if(pos>=bufsize) {
bufsize += CHUNK_SIZE;
buf = realloc(buf, bufsize);
if(buf==NULL) {...erreur out of mem...}
}
}
}

// ajout du '' final
buf[pos++] = 0;

// on reduit le buffer à la taille nécéssaire.
buf = realloc(buf, pos);
if(buf==NULL) {...erreur out of mem...}

return buf;
}



de mon expérience avec nntp, les lignes ne sont pas très grandes, 1024
est extrêmement confortable.

maintenant je voudrais modifier mon programme pour pouvoir entrer une
nouvelle commande.
--
« La vie ne se comprend que par un retour en arrière,
mais on ne la vit qu'en avant. »
(Sören Kierkegaard)
Avatar
unbewusst.sein
Marc Espie wrote:


Une autre possibilite consiste a utiliser fdopen et laisser faire la
bibliotheque standard. Seul risque de cette possibilite: cela condamne une
utilisation ulterieure de la socket en mode non-bloquant (ben oui, aucune
garantie que stdio fonctionne avec des fd en non bloquant).

je ne saurais trop te conseiller de te procurer un peu de litterature,
comme le "network programming " de Stevens...



en effet, la prochaine étape est de passer des commandes sous formes
'interactive" càd non bloquantes.
--
« La vie ne se comprend que par un retour en arrière,
mais on ne la vit qu'en avant. »
(Sören Kierkegaard)
Avatar
xtof.pernod
Le 14/06/2010 06:41, Une Bévue a fait rien qu'à écrire :
Marc Espie wrote:

[fdopen() etc.]

je ne saurais trop te conseiller de te procurer un peu de litterature,
comme le "network programming " de Stevens...



en effet, la prochaine étape est de passer des commandes sous formes
'interactive" càd non bloquantes.



? hum .. quoi de plus bloquant qu'un prog. interactif ?
Je suis pas sur qu'on soit sur la meme longueur d'onde..


Bon, sinon, je veux pas te casser dans ton élan, mais si c'est juste
histoire de balancer quelques commandes à un serveur news, tu peux
y arriver comme suit:

~/cd# telnet news.mon-fai.fr 119
200 Bienvenue sur reader.news.fai.fr, le serveur de news est disponible.
- (posting ok)
list
215 Newsgroups in form "group high low flags".
alt.fan.mac-wisler 0000000000 0000000001 y
(...)
alt.cyberspace.construction.business No description.
.
500 What?
205 Transferred 2464658 bytes in 0 articles, 0 groups. Disconnecting.


Bon, ça peut servir pour débugguer, et c'est toujours plus gratifiant
de se servir de la roue qu'on vient juste d'arriver à faire tourner, hein =)

--
christophe.
Avatar
unbewusst.sein
xtof.pernod wrote:

Bon, sinon, je veux pas te casser dans ton élan, mais si c'est juste
histoire de balancer quelques commandes à un serveur news, tu peux
y arriver comme suit:

~/cd# telnet news.mon-fai.fr 119



ça je sais faire.

--
« La vie ne se comprend que par un retour en arrière,
mais on ne la vit qu'en avant. »
(Sören Kierkegaard)
1 2