2009-12-06 9 views
1

j'ai un programme C existant qui imprime un certain nombre de messages d'erreur standard en utilisant:envoyer des messages formatés sur connexion TCP

fprintf(stderr, ... 

Je souhaite modifier ce programme afin que ces messages sont également envoyés sur une Connexion TCP sur Internet. (Ce que j'ai déjà créé en tant que socket SOCK_STREAM.) Quelle est la meilleure façon de formater les messages comme ils le feraient par fprintf et ensuite les envoyer sur Internet?

Bien sûr, avant de pouvoir envoyer un message, je dois d'abord savoir combien de temps il est, donc je peux d'abord envoyer la longueur au client, afin que le client sache combien d'octets ...

Toutes les idées seraient très appréciées!

Répondre

0

Je pense que vous devez regarder sprintf ou (mieux) la variante qui nécessite que vous fournissiez une taille de tampon de sortie explicite.

3

Une fois que votre socket est connectée, vous pouvez l'ouvrir en tant que flux en utilisant fdopen() sur le descripteur de fichier socket. Cela vous donnera un FILE * que vous pouvez passer à fprintf() à la place de stderr.

+0

Merci, mais j'ai pensé à cela, et pour autant que je sache, pour que le client sache combien d'ines pour lire pour chaque message, je vais d'abord besoin d'envoyer la longueur du message à l'avance . Je ne pense pas que cela puisse être fait en passant simplement FICHIER * à la place de stderr ... – Charles

+0

Eh bien, si tous vos messages se terminent par un '\ n', le client peut simplement lire jusqu'à ce qu'il en voie un. – caf

+0

... ce qui est facile à faire en utilisant 'fgets()', 'fscanf()', etc. sur le côté lecture une fois que vous avez 'FILE *' en utilisant 'fdopen()'. – mark4o

1

Je vous suggère d'encapsuler les appels de sortie dans une fonction d'argument variable (c'est le fonctionnement de la famille de fonctions printf) et de tout faire à partir de là. Par exemple, cela peut ressembler à:

int multi_log(FILE * stream, int fd, const char * fmt, ...) { 
    char buff[BUFF_MAX] = {0}; 
    int len = 0; 
    va_list args; 
    va_start (args, fmt); 
    len = vsnprintf (buff, BUFF_MAX, fmt, args); 
    va_end (args); 

    fputs (buff, stream); 
    write (fd, buff, len); 
} 

De cette façon, vous pouvez ajouter et/ou supprimer des fonctionnalités si nécessaire.

appliquent pour l'utilisation de mises en garde de la taille de retour soigneusement

0

de vsnprintf, vous lisez les pages de manuel Vous rendant plus difficile qu'il doit être. Si vous envoyiez des données binaires et que le client avait besoin de reconnaître les limites des messages, alors oui, vous voudriez d'abord envoyer la longueur du message, ou utiliser une sorte de «cadrage» pour délimiter les limites du message. Mais dans ce cas, vous n'avez pas besoin de ça. Vous pouvez simplement écrire le texte du message sur le socket, en utilisant une approche telle que suggérée ci-dessus. À l'autre extrémité, le pair peut simplement s'asseoir dans une lecture de boucle de texte jusqu'à ce que le socket soit fermé. Si vous voulez que le lecteur traite le texte ligne par ligne, vous pouvez marquer la fin de chaque ligne avec un caractère de nouvelle ligne. Le lecteur peut alors simplement parcourir le texte reçu à la recherche de ces caractères de nouvelle ligne. La seule chose qui pourrait être difficile est que, parce que TCP est orienté sur les octets et non sur les messages, le lecteur n'obtiendra pas toujours le texte dans les morceaux de la même taille que ceux envoyés par l'expéditeur. (Habituellement vous le ferez, mais ce n'est pas garanti.) Votre lecteur doit donc être capable de gérer le cas où une seule lecture de la socket pourrait faire partie d'une ligne, ou peut-être plusieurs lignes combinées ensemble. Ce n'est pas un gros problème, tant que vous codez pour la possibilité que cela puisse arriver.

Questions connexes