2017-03-15 4 views
0

Ayant à l'esprit de communiquer avec une socket de domaine Unix multi-client sans saisie au clavier, je souhaite créer un descripteur de fichier qui remplace stdin.Créer un descripteur de fichier qui remplace stdin (dans select())

Avec une prise multi-client, vous devez ajouter le descripteur de fichier stdin (qui est 0, avec FD_SET(0, &readfds)) à readfds afin d'envoyer l'entrée du clavier (FD_ISSET(0, &readfds)) au serveur. Comme je ne veux pas écrire à chaque fois que je lance mon client, je veux remplacer ce descripteur par un fichier personnalisé (en écrivant dans ce fichier à partir d'un autre programme).

J'ai vérifié Create a file descriptor pour créer deux programmes:

Celui qui écrit au descripteur de fichier:

int main() { 
    char buffer[] = "test"; 
    int fd = open("sample.dat", O_WRONLY | O_CREAT, 0666); 
    dup2(fd, 5); 

    if(write(5, buffer, 4) < 0) 
     fprintf(stderr, "write %s\n", strerror(errno)); 

    close(5);  
    return 0; 
} 

Et un autre qui lit de lui:

int main() { 
    char buffer[4]; 
    int fd = open("sample.dat", O_RDONLY); 
    dup2(fd, 5); 

    for(;;) { 
     if(read(5, buffer, 4) < 0) 
      fprintf(stderr, "read %s\n", strerror(errno)); 

     printf("%s\n", buffer); 
     sleep(1); 
    } 

    return 0; 
} 

Ma question est: est-il possible de rendre ce descripteur de fichier comme stdin-like? Je veux dire en fait mon deuxième programme a lu "test" indéfiniment parce que (bien sûr) sample.dat contient toujours "test" mais je veux le supprimer une fois qu'il a été lu.

+0

Ce que vous demandez n'est pas très clair: qu'entendez-vous par "stdin-like"? –

+0

@ChrisTurner quand vous lisez quelque chose de stdin vous ne le lisez qu'une seule fois, pas infiniment parce que stdin "supprime"/"nettoie" (je ne sais pas exactement comment ça marche) une fois qu'il a été lu – Rallph

Répondre

0

Si j'ai bien compris, vous voulez communiquer avec un programme qui ne peut lire que sur le stdin. Vous avez deux façons d'écrire dans stdin: la première consiste à utiliser votre clavier, et la seconde à utiliser write().

#include <unistd.h> 
#include <string.h> 

int   main(void) 
{ 
    char *s = "what you want to write"; 
    write(STDIN_FILENO, s, strlen(s)); 
    return (0); 
} 

Ce programme va écrire sur le stdin, comme vous le feriez avec votre clavier. En outre, vous verrez la chaîne imprimée sur votre interface de ligne de commande.

+0

J'ai déjà essayé de le remplacer par 'write' mais il apparaît' FD_ISSET' (http: // man7.org/linux/man-pages/man2/select.2.html) ne l'accepte pas – Rallph

+0

Vous voulez dire faire FD_ISSET (0, ensemble)? – tfontain

+0

oui mais en remplaçant le 0 (parce que je ne veux pas d'entrée au clavier) par quoi que ce soit d'autre (comme un autre descripteur de fichier) – Rallph

0

Le problème n'est pas que vous lisez constamment "test", c'est que vous ne gérez pas l'appel à read() correctement. Pendant que vous vérifiez qu'il ne retourne pas une erreur, vous ne voyez pas le nombre d'octets qui ont été lus. read() ne termine pas la chaîne comme nulle, donc vous devriez stocker la valeur de retour et l'utiliser pour mettre le NUL dans votre tampon. Sinon, puisque rien dans le tampon ne change, il apparaîtra comme si vous relisiez le même texte encore et encore.

int err=read(fd, buffer, 4); 
    if(err < 0) 
     { 
     fprintf(stderr, "read %s\n", strerror(errno)); 
     } 
    else 
     { 
     buffer[err]='\0'; 
     } 

Si vous faites ce changement, vous constaterez que vous ne jamais lu dans « test » une fois et après que vous n'êtes pas quoi que ce soit la lecture plus

. Remarque: vous n'avez pas besoin les appels à dup2() - c'est juste pour copier un descripteur de fichier à la valeur connue. Vous pouvez simplement utiliser fd comme dans vos appels pour lire/écrire des données.

+0

Ho oui cela fonctionne merci, il ne lit pas "test" pour toujours mais .. quand je mets à jour le fd en écrivant "tess" dedans, il continue à lire n'importe quoi. Il lit seulement "tess" si je "CTRL + C" et le relance – Rallph