2016-05-17 4 views
0

Ich simuliere einen Chat-Dienst in C-Sprache Ich sende eine Mensage zur Server-Seite wie "U: Benutzername, Passwort; um einen Benutzer anzumelden, aber wenn ich frage, wer online ist, drucke es n-mal der Name des Benutzers), der fragt Was nicht das erwartete Verhalten ist. Jemand kann mir sagen, warumWarum meine Simulation von Chat-Dienst falschen Inhalt schreiben?

?

server.c

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <string.h> 
#include <termios.h> 
#include <linux/stat.h> 

#define FIFO_FILE "MYFIFO" 

typedef struct online { 
char* user; 
struct online* next; 
} online; 

typedef struct users{ 
char* name; 
char* password; 
} users; 

online* begin=NULL; 
online* end=NULL; 
FILE *fp; 
void start_server(); 

void add_online(char* user); 

void realocate_end(); 

void remove_online(char* user); 

char* user_access(char* s); 



void who_online(); 

void free_all(); 

int find_username(char* user); 

void add_user_regist(char* user,char* password); 

users* find_user_regist(char* user, char* password); 

int main(int argc, char *argv[]) 
{ 
if(argc>1){ 
    char password[50]; 
    char password2[50]; 

    printf("Password? "); 
    scanf("%s",password); 
    printf("Repita a password? "); 
    scanf("%s",password2); 

    if(strcmp(password,password2)!=0){ 
    printf("Passwords diferentes!\n"); 
    exit(1); 
    } 

    if(find_username(argv[1])){ 
    printf("Utilizador ja existe\n"); 
    exit(1); 
    } 
    add_user_regist(argv[1],password); 
    printf("Utilizador %s adicionado.\n",argv[1]); 
    exit(0); 
} 


char readbuf[250]; 

/* Create the FIFO if it does not exist */ 
umask(0); 
mknod(FIFO_FILE, S_IFIFO|0666, 0); 
printf("Servidor iniciado.\nEm modo de espera de mensagens\n"); 

while(1) 
{ 
    fp = fopen(FIFO_FILE, "r"); 
    fgets(readbuf, 250, fp); 
    fclose(fp); 
    if(readbuf[0]=='U') 
    user_access(readbuf); 
    if(readbuf[0]=='W') 
    who_online(); 
    printf("Received string: %s\n",readbuf); 


} 
return(0); 
} 



void realocate_end(){ 
online* tmp=begin; 
while(tmp!=NULL){ 
    if(tmp->next==NULL) 
    end=tmp; 
    tmp=tmp->next; 
} 
} 

void remove_online(char* user){ 
online* tmp=begin; 
char path[100]; 
sprintf(path,"/tmp/chatroom_%s",user); 
unlink(path); 
while(tmp!=NULL){ 
    if(tmp->user==user && tmp->user == end->user){ 
    free(end); 
    end=NULL; 
    realocate_end(); 
    } 
    else if(tmp->user==user && tmp->user == begin->user){ 
    begin=begin->next; 
    free(tmp); 
    break; 

    } 
    else if(tmp->next->user ==user){ 
    online* tmp2 = tmp->next->next; 
    free(tmp->next); 
    tmp->next = tmp2; 
    realocate_end(); 
    break; 
    } 
    tmp=tmp->next; 
} 
} 

void add_online(char* user){ 
online* tmp = (online*)malloc(sizeof(online)); 
tmp->user = user; 
tmp->next = NULL; 


if(begin==NULL){ 
    begin = tmp; 
    end=tmp; 
} 
else{ 
    end->next=tmp; 
    end=end->next; 
} 
} 

void who_online(){ 
online* tmp = begin; 
while(tmp!=NULL){ 
    printf("%s\n",tmp->user); 
    tmp=tmp->next; 
} 
} 

void free_all(){ 
while(begin!=NULL){ 
    online* tmp = begin->next; 
    free(begin); 
    begin = tmp; 
} 
} 

int find_username(char* user){ 
FILE* fp; 
char line[50]; 
fp=fopen("./regist", "r"); 
while(fscanf(fp,"%s",line)!=EOF){ 
    char* name=strtok(line,","); 
    if(strcmp(name,user)==0){ 
    fclose(fp); 
    return 1; 
    } 
} 
return 0; 
} 

char* user_access(char* s){ 
int i=0 ,begin=2; 
strtok(s,":"); 
char* username=strtok(NULL,","); 
char* password=strtok(NULL,";"); 

add_online(username); 


} 

users* find_user_regist(char* user, char* password){ 
    FILE* fp; 
    char line[50]; 

    users* tmp = (users*) malloc(sizeof(users)); 

    fp=fopen("./regist", "r"); 
    while(fscanf(fp,"%s",line)!=EOF){ 
    tmp->name =strtok(line,","); 
    tmp->password = strtok(NULL,";"); 
    if(strcmp(tmp->name,user)==0 && strcmp(tmp->password,password)==0){ 
    fclose(fp); 
    return tmp; 
    } 


    } 
    fclose(fp); 
    return NULL; 
} 

void add_user_regist(char* user,char* password){ 
    FILE* fp; 
    fp=fopen("./regist", "a"); 
    if(fp==NULL) 
    fp=fopen("./regist", "w"); 
    fprintf(fp,"%s,%s;\n",user,password); 
    fclose(fp); 
} 

client.c

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/stat.h> 
#include <unistd.h> 
#include <termios.h> 
#include <linux/stat.h> 


#define FIFO_FILE "MYFIFO" 


int main(int argc, char *argv[]) 
{ 
    FILE *fp; 

    char user[50]; 
    char password[50]; 

    if(argc==1){ 
    printf("Não escolheu utilizador\n"); 
    exit(0); 
    } 

    sprintf(user,"%s",argv[1]); 
    printf("Password:\n"); 
    scanf("%s",password); 
    getchar(); 

    char mensagem[250]; 

    if((fp = fopen(FIFO_FILE, "w")) == NULL) { 
    perror("fopen"); 
    exit(1); 
    } 
    char path [100] ; 

    strcpy(path,"."); 
    strcat(path,user); 
    umask(0); 
    mknod(path, S_IFIFO|0666, 0); 

    sprintf(mensagem,"U:%s,%s;",user,password); 
    fputs(mensagem, fp); 
    fclose(fp); 

    while(1){ 

    printf("**Menu**\n1) Listar utilizadores online\n2) Mandar SMS a um utilizador\n3) Logout\n\n"); 

    char opcao; 
    scanf("%c",&opcao); 
    char lixo=getchar(); 

    if(opcao!='1' && opcao!='2' && opcao!='3') 
     continue; 
    if(opcao=='1'){ 
     if((fp = fopen(FIFO_FILE, "w")) == NULL) { 
     perror("fopen"); 
     exit(1); 
    } 
    sprintf(mensagem,"W:%s;",user); 
    fputs(mensagem, fp); 
    fclose(fp); 
    } 
    else if(opcao=='2'){ 

    if((fp = fopen(FIFO_FILE, "w")) == NULL) { 
     perror("fopen"); 
     exit(1); 
    } 

    memset(mensagem,0,sizeof(mensagem)); 
    scanf("%s",mensagem); 
    char lixo=getchar(); 
    fputs(mensagem, fp); 
    fclose(fp); 
    } 
    else if(opcao=='3'){ 
    break; 
    } 

    } 



    return(0); 
} 
+1

Stackoverflow-Dienst kein Debugging ist zu befreien. Verwenden Sie einen Debugger, um die Problembereiche einzugrenzen. Stellen Sie jedoch zuerst sicher, dass alle Strings ordnungsgemäß terminiert sind, und denken Sie daran, dass Pipes (die ein FIFO ist) eine * streaming * -Kommunikationsmethode ohne festgelegte Nachrichtengrenzen ist. Das bedeutet, dass ein Empfang möglicherweise weniger als eine vollständige Nachricht oder mehr empfängt, und Sie müssen eine Art Protokoll oben auf dem Stream implementieren, um Nachrichtengrenzen selbst einzuführen (z. B. mit Start/Stopp-Sequenzen oder einer Nachrichtengröße fester Länge) Header). –

Antwort

1

Dies ist ein Ergebnis wäre, von dir zu vergessen, neuen Speicher zu reservieren, um die u sername für jeden einzelnen Benutzer. Die Art und Weise, wie Sie es tun, weist nun jedem Benutzer einen neuen Speicher für einen Zeiger auf eine Zeichenkette zu - nicht der eigentlichen Zeichenkette.

Wenn Sie den Pfad der Wert, den Sie speichern in der Struktur durch die Funktion folgen Anrufe, die Sie werden sehen, dass jeder Datensatz verweist auf die readbuf Arrays

diese Bedenken Sie:

char readbuf[250] = "U:name,password;" 
user_access(readbuf); 

In user_access char *s Punkte der Anfang der Zeichenfolge, nämlich U. Der zweite Aufruf an strtok gibt den Zeiger an den Anfang des Benutzernamens n zurück und ersetzt , durch einen Null-Terminator.

Zum Zeitpunkt des Anrufs add_online der Puffer sieht nun so etwas wie dieses "U\0name\0password\0\0" mit username zur c-string zeigt "name" gespeichert noch in readbuf

Wenn Sie einen neuen Knoten in der Liste verknüpft erstellen Sie einfach zuweisen der Zeiger auf diese C-Zeichenfolge im Readbuf, als solche die Benutzernamen ändern sich je nachdem, was in Ihrem Puffer ist. Da der W-Befehl nur aus einem Zeichen besteht, ist der letzte an den Server gesendete Benutzername im Puffer intakt.

Um dies zu beheben, können Sie einfach neuen Speicher für jeden Benutzernamen zuweisen und die Zeichenfolgen kopieren.

void add_online(char* user){ 
    online* tmp = (online*) malloc(sizeof(online)); 
    tmp->user = (char*) malloc(strlen(user)*sizeof(char)); 
    strcpy(tmp->user, user); 
    tmp->next = NULL; 


    if (begin==NULL){ 
     begin = tmp; 
     end=tmp; 
    } 
    else { 
     end->next=tmp; 
     end=end->next; 
    } 
} 

Ebenso sollten Sie den reservierten Speicher für den Benutzernamen freizugeben, wenn die Struktur

Verwandte Themen