2016-06-01 1 views
1

연결 한 클라이언트가 서로 메시지를 보낼 수있게하는 서버를 작성하려고합니다. 메시지를 수신하여 대기열에 넣고 서버 - 클라이언트 통신 (함수 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

@Lewis 글쎄,하지만 당신이 처리 할 병행성에주의를 기울이십시오. – LPs

+0

Hm 동시성 ..? :// 그게 무슨 뜻인지는 모르겠지만 ... 순서대로 스레드를 실행하는 프로그램입니까? 내가하려고하는 것을 성취 할 수있는 또 다른 방법이 있습니까? 나는 전에 포크를 사용하지 않았고, 기억이 같다고 생각했다. 단지 지침이 과정에서 과정으로 바뀌었다. ... – Lewis

0

를 사용하여 스레드됩니다. 두 개의 스레드를 시작하십시오. 하나는 듣기위한 것이고 다른 하나는 대답하기위한 것입니다.

포크는 동일한 코드를 공유하지만 데이터 세그먼트가 다른 새 OS 프로세스를 만듭니다. 따라서 한 프로세스에서 변경되는 사항은 다른 프로세스에서 변경되지 않습니다.

+0

그 말이 틀림 없습니다! 스레드를 사용해 보겠습니다. 감사합니다. – Lewis

관련 문제