2017-04-04 5 views
-1

Je veux construire un programme de discussion, mais le problème est qu'une fois que le client envoie un message au serveur, tous les autres clients recevront ce message du serveur, mais le client don Je ne sais pas quand le message viendra. Dans la boucle principale du client, il bloquera sur fgets() et attendra que l'utilisateur entre une commande ou un message. J'ai besoin du programme client pour recevoir le message et l'imprimer en attendant la saisie de l'utilisateur. Comment puis je faire ça ?c Programme de discussion TCP, le client ne sait pas quand recer

voici le code: Je n'ai pas écrit recv pour le message puisque je ne sais pas où le mettre.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/time.h> 
#include <sys/socket.h> 
#include <netdb.h> 
#include <arpa/inet.h> 
#include <netinet/in.h> 
#include <unistd.h> 
#include <time.h> 

#define LOGIN 1 
#define LO_ACK 2 
#define LO_NACK 3 
#define EXIT 4 
#define JOIN 5 
#define JN_ACK 6 
#define JN_NACK 7 
#define LEAVE_SESS 8 
#define NEW_SESS 9 
#define NS_ACK 10 
#define MESSAGE 11 
#define QUERY 12 
#define QU_ACK 13 

struct packet { 
    unsigned int type; 
    unsigned int size; 
    char source[20]; 
    char data[500]; 
}; 

int encode(struct packet temp, char *data) { 

    sprintf(data, "%d:%d:%s:", temp.type, temp.size, 
      temp.source); 

    int length = strlen(data); 

    int i; 
    for (i = 0; i < temp.size; i++) { 
     data[length + i] = temp.data[i]; 
    } 
    data[length + i] = '\0'; 

    return length; 
} 

struct packet decode(char *data) { 
    int i, j; 
    struct packet message; 
    char temp[100]; 
    char source[20]; 

    sscanf(data, "%d:%d", &message.type, &message.size); 

    sprintf(temp, "%d:%d", message.type, message.size); 

    int length = strlen(temp); 

    for (i = length + 1; data[i] != ':'; i++) { 
     message.source[i - length - 1] = data[i]; 
    } 

    for (j = 0; j < message.size; j++) { 
     message.data[j] = data[j + i + 1]; 
    } 

    return message; 

} 

int main(void) { 
    int sockfd, numbytes; 
    struct addrinfo hints, *servinfo, *p; 
    int rv; 
    int login = 0; 
    char me[20]; 


    while (1) { 
     char buf[500]; 
     char input[100]; 
     char *command; 
     char arg1[20], arg2[20], arg3[20], arg4[20], arg5[20]; 
     int i, j, k, l, m; 

     fgets(input, 100, stdin); 

     if (strlen(input) < 3) 
      continue; 

     if (input[0] == '/') {//command 
      command = &input[1]; 

      //get first argument 
      for (i = 0; command[i] != '\0' && command[i] != ' '; i++) { 
       arg1[i] = command[i]; 
      } 
      //arg1[i] = '\0'; 

      if (strcmp(arg1, "login") == 0) {//login 
       //get id,password,ip,port 
       if (login == 1) { 
        printf("error: already login\n"); 
        continue; 
       } 

       for (j = i + 1; command[j] != '\0' && command[j] != ' '; j++) {//id 
        arg2[j - i - 1] = command[j]; 
       } 
       //arg1[j-i+1] = '\0'; 
       for (k = j + 1; command[k] != '\0' && command[k] != ' '; k++) {//password 
        arg3[k - j - 1] = command[k]; 
       } 

       for (l = k + 1; command[l] != '\0' && command[l] != ' '; l++) {//ip 
        arg4[l - k - 1] = command[l]; 
       } 

       for (m = l + 1; command[m] != '\0'; m++) {//port 
        arg5[m - l - 1] = command[m]; 
       } 

       memset(&hints, 0, sizeof hints); 
       hints.ai_family = AF_UNSPEC; 
       hints.ai_socktype = SOCK_STREAM; 

       if ((rv = getaddrinfo(arg4, arg5, &hints, &servinfo)) != 0) { 
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 
        return 1; 
       } 

       for (p = servinfo; p != NULL; p = p->ai_next) { 
        if ((sockfd = socket(p->ai_family, p->ai_socktype, 
          p->ai_protocol)) == -1) { 
         perror("client: socket"); 
         continue; 
        } 
        if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) { 
         close(sockfd); 
         perror("client: connect"); 
         continue; 
        } 
        break; 
       } 

       if (p == NULL) { 
        fprintf(stderr, "client: failed to connect\n"); 
        return 2; 
       } 

       freeaddrinfo(servinfo); 

       struct packet tosend; 
       tosend.type = LOGIN; 
       sprintf(tosend.data, "%s %s", arg2, arg3); 
       strcpy(tosend.source, arg2); 
       tosend.size = strlen(tosend.data); 

       char message[500]; 
       encode(tosend, message); 

       send(sockfd, message, strlen(message), 0); 

       usleep(100); 
       recv(sockfd, buf, strlen(buf), 0); 
       struct packet reply; 
       reply = decode(buf); 

       if (reply.type == LO_ACK) { 
        printf("login successful\n"); 
        strcpy(me, arg2); 
        login = 1; 
        continue; 
       } else if (reply.type == LO_NACK) { 
        printf("login failed: %s\n", reply.data); 
        continue; 
       } 

      } else if (strcmp(arg1, "createsession") == 0) { 
       if (login == 0) { 
        printf("error: not login\n"); 
        continue; 
       } 

       for (j = i + 1; command[j] != '\0'; j++) {//session name 
        arg2[j - i - 1] = command[j]; 
       } 

       struct packet tosend; 
       tosend.type = NEW_SESS; 
       strcpy(tosend.data, arg2); 
       strcpy(tosend.source, me); 
       tosend.size = strlen(tosend.data); 

       char message[500]; 
       encode(tosend, message); 

       send(sockfd, message, strlen(message), 0); 

       usleep(100); 
       recv(sockfd, buf, strlen(buf), 0); 
       struct packet reply; 
       reply = decode(buf); 

       if (reply.type == NS_ACK) { 
        printf("create session successful\n"); 
        continue; 
       } else if (reply.type == JN_ACK) { 
        printf("session already exist, join session successful\n"); 
        continue; 
       } 
      } else if (strcmp(arg1, "joinsession") == 0) { 
       if (login == 0) { 
        printf("error: not login\n"); 
        continue; 
       } 

       for (j = i + 1; command[j] != '\0'; j++) {//session name 
        arg2[j - i - 1] = command[j]; 
       } 

       struct packet tosend; 
       tosend.type = JOIN; 
       strcpy(tosend.data, arg2); 
       strcpy(tosend.source, me); 
       tosend.size = strlen(tosend.data); 

       char message[500]; 
       encode(tosend, message); 

       send(sockfd, message, strlen(message), 0); 

       usleep(100); 
       recv(sockfd, buf, strlen(buf), 0); 
       struct packet reply; 
       reply = decode(buf); 

       if (reply.type == JN_ACK) { 
        printf("join session successful\n"); 
        continue; 
       } 
      } else if (strcmp(arg1, "leavesession") == 0) { 
       if (login == 0) { 
        printf("error: not login\n"); 
        continue; 
       } 

       struct packet tosend; 
       tosend.type = LEAVE_SESS; 
       strcpy(tosend.data, "none"); 
       strcpy(tosend.source, me); 
       tosend.size = strlen(tosend.data); 

       char message[500]; 
       encode(tosend, message); 

       send(sockfd, message, strlen(message), 0); 

       printf("leave session successful\n"); 

       continue; 
      } else if (strcmp(arg1, "list") == 0) { 
       if (login == 0) { 
        printf("error: not login\n"); 
        continue; 
       } 

       struct packet tosend; 
       tosend.type = QUERY; 
       strcpy(tosend.data, "none"); 
       strcpy(tosend.source, me); 
       tosend.size = strlen(tosend.data); 

       char message[500]; 
       encode(tosend, message); 

       send(sockfd, message, strlen(message), 0); 

       usleep(100); 
       recv(sockfd, buf, strlen(buf), 0); 
       struct packet reply; 
       reply = decode(buf); 

       printf("%s", reply.data); 

       continue; 
      } else { 
       printf("invalid command\n"); 
       continue; 
      } 

     } else {//message 
      if (login == 0) { 
       printf("error: not login\n"); 
       continue; 
      } 

      struct packet tosend; 
      tosend.type = MESSAGE; 
      strcpy(tosend.data, input); 
      strcpy(tosend.source, me); 
      tosend.size = strlen(tosend.data); 

      char message[500]; 
      encode(tosend, message); 

      send(sockfd, message, strlen(message), 0); 

      continue; 
     } 
    } 
} 
+1

Ce n'est pas comme ça que ça fonctionne. Vous ne pouvez pas nous demander d'écrire du code pour vous. Montrez vos efforts. Nous ne pouvons vous aider que si vous soumettez le code. – Arvindsinc2

+0

où? ... s'il vous plaît poster le code – Arvindsinc2

+1

Il y a deux options pour vous. 1) Fils 2) Sélectionnez. Nous devrions vous laisser le soin de les lire et essayer d'écrire * code * pour eux. –

Répondre

0

'client ne sait pas quand recv' c'est facile: tout le temps. Il existe plusieurs options:

1) Sélectionnez() sur fd, y compris stdin (Google pour plus de détails).

2) poll/epoll() - comme ci-dessus, mais performances améliorées. 3) Avoir un thread qui attend en entrée et envoie des messages sur une file d'attente producteur-consommateur vers un autre thread 'state-machine' qui gère ces messages, et des messages d'autres threads qui gèrent les données client recv() du serveur et effectue les actions requises.

4) Tout autre mécanisme pouvant être disponible sur votre système d'exploitation.

0

vérifierons ce code ici:

#include <stdio.h> 
#include <sys/select.h> 
#include <unistd.h> 

int main() 
{ 

    fd_set fds; 

    while(1){ 
     FD_ZERO(&fds); // you NEED to zero this every loop 
     FD_SET(STDIN_FILENO, &fds); 
     // add your socket here 

     // first argument here will be your socket + 1 
     select(STDIN_FILENO + 1, &fds, NULL, NULL, NULL); 
     if (FD_ISSET(STDIN_FILENO, &fds)){ 
       char buffer[128]; 
       fgets(buffer, sizeof(buffer), stdin); 
       printf("User input - stdin: %s", buffer); 
     } 
     // here check if your socket is set and act accordingly 
    } 

    return 0; 
} 

Il lira des extraits de stdin en utilisant select (http://man7.org/linux/man-pages/man2/select.2.html), vous pouvez l'utiliser comme base pour étudier comment sélectionnez des œuvres et l'étendre à vos besoins.

Vous devrez ajouter votre socket dans le fds de sorte qu'il attendra le select jusqu'à ce qu'il y ait une entrée utilisateur à traiter ou qu'il y ait des données sur votre socket (utilisez FD_ISSET pour vérifier).

Bonne chance. PS: J'ai utilisé le code de cette question Using stdin with select() in C comme base pour produire celui que j'ai posté.