2016-06-01 6 views
1

クライアントを接続して相互にメッセージを送信できるサーバーをcで作成しようとしています。私は、メッセージを受信し、キューに配置し、ユーザー名がメッセージと一致する場合、サーバーとクライアントの通信(関数dostuff)がそのメッセージを処理するプロセスを持つようにしました。キューを使用してサーバー上のクライアントメッセージを処理しようとしています[C]

if(Front() != NULL) 
      { 
       strcpy(dest, Front()->dest); 
       if(strcmp(dest, username) == 0) 
       { 
        strcpy(buffer, Front()->text); 
        Dequeue(); 
        n = write(sock,buffer,strlen(buffer)); 
        if (n < 0) error("ERROR writing to socket"); 
       } 
      } 

実行されることはありません:

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

/******Struct msg*********/ 
typedef struct msg 
{ 
    char dest [64]; 
    char origin[64]; 
    char text [256]; 
}msg; 
/*********Queue*********/ 
/*Queue - Linked List implementation*/ 
#include<stdio.h> 
#include<stdlib.h> 
struct Node { 
    msg *data; 
    struct Node* next; 
}; 
struct Node* front = NULL; 
struct Node* rear = NULL; 
void Enqueue(msg *x) { 
    struct Node* temp = 
     (struct Node*)malloc(sizeof(struct Node)); 
    temp->data =x; 
    temp->next = NULL; 
    if(front == NULL && rear == NULL){ 
     front = rear = temp; 
     return; 
    } 
    rear->next = temp; 
    rear = temp; 
} 
void Dequeue() { 
    struct Node* temp = front; 
    if(front == NULL) { 
     printf("Queue is Empty\n"); 
     return; 
    } 
    if(front == rear) { 
     front = rear = NULL; 
    } 
    else { 
     front = front->next; 
    } 
    free(temp); 
} 
msg *Front() { 
    if(front == NULL) { 
     return 0; 
    } 
    return front->data; 
} 
void error(const char *msg) 
{ 
    perror(msg); 
    exit(1); 
} 

int interpret(char *line, char username[]) 
{ 
    //printf("Ready to interpret: %s\n",line); 

    /* 
    char *command, *arg1 , *arg2,l[64]; 
    msg *message; 
    strcpy(l,line); 
    command = strtok(l," "); 

    if(strcmp(command, "/tell") == 0) 
    { 
     printf("The command was vaid!\n");//chegou aqui 
     printf("Ready to interpret: %s\n",l); 
     arg1 = strtok(NULL," "); 
     printf("I got this far!"); 
     arg2 = l + strlen(command) + strlen(arg1) + 2; //somamos dois por causa dos espaços 

     message = (msg*)malloc(sizeof(msg)); 

     //printf("I got this far!"); nao está a chegar aqui 

     strcmp(message->dest, arg1); 
     strcmp(message->origin, username); 
     strcmp(message->text, arg2); 
     Enqueue(message); 
     printf("(%s -> %s) -%s- was placed on the queue",message->origin,message->dest,message->text); 
    } 
    else 
    { 
     printf("comando inválido"); 
    } 

    */ 
     //this is temporary because there is an error with the code above which made the message not be correct 
     msg *message; 
     message = (msg*)malloc(sizeof(msg)); 

     strcmp(message->dest, "dest"); 
     strcmp(message->origin, "origin"); 
     strcmp(message->text, "blahblahblah"); 
     Enqueue(message); 

    return 1; 
} 
void dostuff (int sock, char username[]) 
{ 
    int n, pid; 
    char buffer[256], dest[64]; 
    pid = fork(); 
    while(1) 
    { 
     if(pid > 0) 
     { 
      bzero(buffer,256); 
      n = read(sock,buffer,255); 

      if (n < 0) error("ERROR reading from socket"); 

      printf("Here is the full message: %s\n",buffer); 

      //n = write(sock,"I got your message!\n",18); 
      //if (n < 0) error("ERROR writing to socket"); 

      interpret(buffer, username); 
     } 
     else 
     { 
      sleep(1); 
      if(Front() != NULL) 
      { 
       strcpy(dest, Front()->dest); 
       if(strcmp(dest, username) == 0) 
       { 
        strcpy(buffer, Front()->text); 
        Dequeue(); 
        n = write(sock,buffer,strlen(buffer)); 
        if (n < 0) error("ERROR writing to socket"); 
       } 
      } 
     } 
    } 
} 
int main(int argc, char *argv[]) 
{ 
    int sockfd, newsockfd, portno, pid , f; 
    int userCount;              
    socklen_t clilen; 

    struct sockaddr_in serv_addr, cli_addr;         

    if (argc < 2) 
    { 
     fprintf(stderr,"ERROR, no port provided\n"); 
     exit(1); 
    } 

    sockfd = socket(AF_INET, SOCK_STREAM, 0);        
    if (sockfd < 0) 
     error("ERROR opening socket"); 

    bzero((char *) &serv_addr, sizeof(serv_addr));        

    portno = atoi(argv[1]); 

    serv_addr.sin_family = AF_INET;           
    serv_addr.sin_addr.s_addr = INADDR_ANY;         
    serv_addr.sin_port = htons(portno);          

    if (bind(sockfd, (struct sockaddr *) &serv_addr, 
       sizeof(serv_addr)) < 0) 
       error("ERROR on binding"); 

    listen(sockfd,5);               
    clilen = sizeof(cli_addr); 

    userCount = 0; 
    char dname[64];               
    f = fork(); 

    while (1) 
    { 
     if(f > 0) 
     { 
      newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen); 
      if (newsockfd < 0) error("ERROR on accept"); 

      userCount++;               
      sprintf(dname, "%d", userCount);          

      pid = fork(); 
      if (pid < 0) error("ERROR on fork"); 
      if (pid == 0) 
      { 
       close(sockfd); 
       dostuff(newsockfd, dname); 
       exit(0); 
      } 
      else close(newsockfd); 

     } 
    } 

    close(sockfd); 
    return 0; 
} 

問題は、キューから項目を削除することになっているコードのこの部分があることのようです。 私はこれまでにこのようなことをしたことは一度もなかったので、このアプローチは完全に間違っている可能性があります。誰かが私が何をやっているのかを私に説明したり、別の解決策を提案したりすることができれば、それは素晴らしいことです。

+1

'front'の値を表示するか、デバッガを使用してください。問題は 'front'がNULLだと思われることです。したがって、この機能は決して実行されません。 – Mirakurun

+0

@Mirakurun要素を追加した後にキューが空の場合はメッセージを出力していましたが、その時点でキューは空ではないようですが、それでも条件は満たされません。私はそれがより読みやすくすると思ったので、opのprintステートメントを削除しました。 – Lewis

+0

あなたはタイプミスがあります:すべての 'strcmp'は' interpet'関数本体で 'strcpy'でなければなりません。 – LPs

答えて

0

fork()の後でグローバルを管理する方法について誤解しています。

これらは共有されません。プロセスは変数のコピーを変更することができます。これらの変更は、他の子供/両親に通知されません。

だから、あなたがEnqueueでやろうとしているものをフロントポインタのポインタfrontが、他のチャイルズのコピーが更新されないのローカルコピーに変更を行います。

最小限にあなたのコードの削減:

#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <string.h> 
#include <strings.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 

/******Struct msg*********/ 
typedef struct msg 
{ 
    char dest [64]; 
    char origin[64]; 
    char text [256]; 
}msg; 
/*********Queue*********/ 
/*Queue - Linked List implementation*/ 
#include<stdio.h> 
#include<stdlib.h> 
struct Node { 
    msg *data; 
    struct Node* next; 
}; 
struct Node* front = NULL; 
struct Node* rear = NULL; 

void Enqueue(msg *x) 
{ 
    struct Node* temp = malloc(sizeof(struct Node)); 

    temp->data =x; 
    temp->next = NULL; 

    if(front == NULL && rear == NULL) 
    { 
     front = rear = temp; 
     printf("front: %p\n", (void *)(front)); 
     printf("rear: %p\n" , (void *)(rear)); 
     printf("temp: %p\n" , (void *)(temp)); 
     return; 
    } 

    rear->next = temp; 
    rear = temp; 
} 

void Dequeue(void) { 
    struct Node* temp = front; 
    if(front == NULL) { 
     printf("Queue is Empty\n"); 
     return; 
    } 
    if(front == rear) { 
     front = rear = NULL; 
    } 
    else { 
     front = front->next; 
    } 
    free(temp); 
} 
msg *Front(void) { 
    if(front == NULL) { 
     return 0; 
    } 
    return front->data; 
} 
void error(const char *msg) 
{ 
    perror(msg); 
    exit(1); 
} 

int interpret(void) 
{ 

    //this is temporary because there is an error with the code above which made the message not be correct 
    msg *message; 
    message = (msg*)malloc(sizeof(msg)); 

    strcpy(message->dest, "dest"); 
    strcpy(message->origin, "origin"); 
    strcpy(message->text, "blahblahblah"); 
    Enqueue(message); 

    return 1; 
} 

void dostuff (void) 
{ 
    pid_t pid; 

    pid = fork(); 

    if(pid > 0) 
    { 
     interpret(); 
    } 
    else 
    { 
     sleep(1); 
     printf("\nfront: %p\n", (void *)(front)); 
    } 
} 
int main(int argc, char *argv[]) 
{ 
    pid_t f, pid; 

    f = fork(); 

    if(f > 0) 
    { 
     pid = fork(); 

     if (pid < 0) 
      error("ERROR on fork"); 

     if (pid == 0) 
     { 
      dostuff(); 
     } 
    } 

    return 0; 
} 

出力ではなく、フォークの

front: 0x18371a0 
rear: 0x18371a0 
temp: 0x18371a0 
[email protected]:~$ 
front: (nil) 
+0

ありがとうございます。私はスレッドを使用して、各インスタンスが同じ変数を変更しようとします – Lewis

+0

@ルイスうーん、しかし、あなたが世話をする同時性を持っていることに注意してください... – LPs

+0

Hm同時性..? :/私はそれが何を意味するのかわかりません...プログラムがスレッドを順不同で実行していますか?私がしようとしていることを達成する別の方法がありますか?私は前にフォークを使ったことはなかったし、記憶が同じで、手順だけがプロセスごとに変わったと思いました.... – Lewis

0

使用スレッドになります。 2つのスレッドを開始します。 1つはリスニング用、もう1つは応答用です。

フォークは、同じコードを共有する新しいOSプロセスを作成しますが、データセグメントは異なります。あなたが1つのプロセスで変更するものは別のプロセスでは見えません。

+0

それは理にかなっています!私はスレッドを使用して試してみる、ありがとう – Lewis