IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau C Discussion :

bot IRC: posix threads et autres remarques


Sujet :

Réseau C

  1. #1
    Membre expérimenté Avatar de keikoz
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    146
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 146
    Par défaut bot IRC: posix threads et autres remarques
    Bonjour

    Voilà, je suis un frais codeur en langage C qui fait ses premières armes. J'ai décidé pour commencer de me lancer dans le codage d'un bot irc. J'aimerais ici présenter mon code et vous demander ce que vous en pensez. Je ne vous demande pas de faire du débuggage bien sur, mais plutôt à ce que vous m'aidiez à comprendre s'il y a de grosses boulettes et erreurs de programmation, dans l'optique de faire un code propre. Donc toutes les remarques sont bienvenues, mais il y a un certains nombre de points sur lesquels je m'interroge particulièrement.

    1) J'utilise les posix threads. Le but de l'opération est que le bot soit en situation d'idle, et qu'il puisse autant réagir à des messages arrivant sur la socket, qu'être disponible pour l'envoi de messages. Du coup ça se concrétise avec deux threads, dont l'un appelle une fonction de lecture sur la socket (read_func) et l'autre appelle une fonction d'écriture sur stdin.
    Existe-t-il des moyens plus simples de réaliser cette situation? J'ai vu récemment que je pourrais éventuellement utiliser select() qui permet d'endormir le bot en scrutant une série de descripteurs de fichier. Quelle est la meilleure solution ?

    2) Vous remarquerez que j'utilise des variables globales. Au début je voulais m'en passer totalement, mais c'était galère, les buffer d'écriture et lecture étant utilisés partout dans le code. Est-ce vraiment un problème d'utiliser des variables globales? Serait-il mieux de les éviter ou pas, et pourquoi ?

    Je poste ici juste le fichier principal, qui contient l'essentiel de la structure du programme et suffit pour comprendre son fonctionnement. Le bot au complet, si quelqu'un veut voir le reste, est disponible sur http://keikoz.free.fr/scripts/kbot-0.06.tar.gz .

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <string.h>
    #include <pthread.h>
    #include <netdb.h>
    #include "commands.h"
    #include "irc.h"
    #include "kbot.h"
    #include "files.h"
     
    /* Initialisation des fonctions */
    void *write_funct(void *arg);
    void *read_funct(void *arg);
     
    /* Variables globales. Est-ce mal ? Les buffers sont utilisés tout au long
     * de la connexion ... */
    int Cli_Sock;
    char wBuffer[MAX_BUFFER];
    char rBuffer[MAX_BUFFER];
    pthread_t read_thread, write_thread;
     
     
    int main(int argc, char *argv[])
    {
      int Serv_Port;
      struct sockaddr_in Serv_Addr;
      struct hostent *Server;
     
     
      /* On vérifie que la commande est utilisée correctement */
      if (argc != 3) {
        fprintf(stderr,"Usage: kbot hostname port\n");
        exit(1);
      }
      else {
        Serv_Port = atoi(argv[2]);
        if (Serv_Port < 1 || Serv_Port > 65355) {
          fprintf(stderr, "Invalid port\n");
          exit(1);
        }
      }
     
     
      /* Appel du fichier de configuration */
      conf_file_open();
     
     
      /* On créé l'adresse serveur avec les paramètres de connexion */
      Server = gethostbyname(argv[1]);
      Serv_Addr.sin_family = AF_INET;
      Serv_Addr.sin_port = htons(Serv_Port);
      memcpy(&Serv_Addr.sin_addr.s_addr, Server->h_addr, Server->h_length);
     
     
      /* On établi le socket (pourquoi AF_INET et pas PF_INET ?) */
      Cli_Sock = socket(AF_INET, SOCK_STREAM, 0);
      if (Cli_Sock < 0) {
        fprintf(stderr,"Erreur lors de la création du socket\n");
        exit(1);
      }
     
     
      /* On établit la connection sur le socket */
      if(connect(Cli_Sock, (struct sockaddr*) &Serv_Addr, sizeof(Serv_Addr))!= 0) {
        fprintf(stderr,"Erreur lors de la connection\n");
        exit(1);
      }
     
     
      /* Threads (écriture, lecture) */
      pthread_create(&write_thread, NULL, write_funct, NULL);
      pthread_create(&read_thread, NULL, read_funct, NULL);
     
     
      /* On rejoint les thread lors de leur fin d'exécution) */
      pthread_join(write_thread, NULL);
      pthread_join(read_thread, NULL);
     
      return 0;
    }
     
     
    /* fonctions d'écriture/lecture dans le socket */
    void *write_funct (void *arg)
    {
      /* Modules */
      auth();
     
      /* Boucle: Processus d'écriture */
      while (1) {
        memset(wBuffer, 0, MAX_BUFFER);
        fgets(wBuffer, MAX_BUFFER-1, stdin);
     
        commands();
     
        if (write(Cli_Sock, wBuffer, strlen(wBuffer)) < 0)
          fprintf(stderr,"Error writing to socket\n");
      }
      return(0);
    }
     
    void *read_funct (void *arg)
    {
      while (1) {
        int n;
     
        memset(rBuffer,0, MAX_BUFFER);
        n = recv(Cli_Sock, rBuffer, MAX_BUFFER, 0);
     
        /* Situation d'écriture normale. Revoir cette partie pour intégrer le traitement des commandes irc (qui se terminent par un \r\n) */
        if (n > 0) {
     
          /* Ecriture sur stdout */
          printf(">%s", rBuffer);
     
          /* Modules */
          on_ping();
     
        }
     
        /* Cas erreur */
        else if (n < 0) 
          fprintf(stderr,"Error reading from socket\n");
     
        /* Fermeture du socket distant */
        else if (n == 0) {
          if (close(Cli_Sock) != 0)
    	fprintf(stderr, "Could not close the socket\n");
          printf("Fin de la connection\n");
          pthread_exit(&read_thread);
        }
     
      }
      return(0);
    }

  2. #2
    Membre éprouvé
    Avatar de granquet
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    1 201
    Détails du profil
    Informations personnelles :
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 201
    Par défaut
    select marche tres bien dans ce genre de cas

    perso, je recommande.

    le seul probleme de select, c'est que sous windows, tu ne peux pas ajouter STDIN_FILENO a la liste des descripteurs a "scruter".

    concernant les globales, çaymal (en general)
    emmanuel as ecris une note dessus: http://emmanuel-delahaye.developpez....s.htm#globales

  3. #3
    Membre expérimenté Avatar de keikoz
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    146
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 146
    Par défaut
    Merci pour la réponse,

    j'ai pas mal repris ce bot et tout réécrit sur la base de select. Le tout marche plutôt bien.

    J'ai aussi éliminé les variables globales, mais à ce propos est-ce qu'il faut aussi éviter les globales statiques (je ne sais pas si alors les appeler "globales" est vraiment correct, dans ce cas), style "static int" en début de fichier ?

  4. #4
    Membre extrêmement actif

    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Juin 2003
    Messages
    4 506
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 506
    Par défaut
    Une variable globale est static (dans la zone mémoire statique) donc ajouter le qualificateur static ne sert à rien à moins que la norme du C est prévu quelque chose dans ce cas ?

  5. #5
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par hegros
    Une variable globale est static (dans la zone mémoire statique) donc ajouter le qualificateur static ne sert à rien à moins que la norme du C est prévu quelque chose dans ce cas ?
    Ben oui, ça limite la portée à l'unité de compilation courante...

  6. #6
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par keikoz
    J'ai aussi éliminé les variables globales, mais à ce propos est-ce qu'il faut aussi éviter les globales statiques (je ne sais pas si alors les appeler "globales" est vraiment correct, dans ce cas), style "static int" en début de fichier ?
    Oui.

    http://emmanuel-delahaye.developpez....s.htm#globales

  7. #7
    Membre expérimenté Avatar de keikoz
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    146
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 146
    Par défaut
    D'accord,

    merci beaucoup pour les réponses

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Bot irc, questions !
    Par Fabouney dans le forum Programmation et administration système
    Réponses: 4
    Dernier message: 02/08/2006, 11h28
  2. bot irc: problème d'affichage et d'envoie
    Par alceste dans le forum C++
    Réponses: 21
    Dernier message: 21/06/2006, 14h47
  3. Creation d'un bot IRC
    Par kedare dans le forum Bibliothèques tierces
    Réponses: 2
    Dernier message: 28/11/2005, 21h29
  4. segment memoire partagee, thread, ou autre?
    Par Pouic dans le forum POSIX
    Réponses: 9
    Dernier message: 26/10/2004, 18h54

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo