2011-04-06 21 views
3

udp를 사용하여 안정적인 파일 전송을 만들었지 만 하나의 클라이언트 만 처리합니다. 그래서 fork()를 사용하여 서버가 여러 클라이언트를 처리하도록하는 방법을 생각했습니다. 그러나 나는 어떻게 진행해야 할지를 정말로 모른다. 현재로서는 클라이언트 쪽을 변경할 필요가 없으며 서버가 더러운 작업을 수행 할 것임을 알고 있습니다. 그 문제를 해결하는 방법에 대한 어떤 생각이나 아이디어도 크게 감사하겠습니다. 시. 여기에 내가 시작하는 방법입니다멀티 스레드 udp 서버/클라이언트

int main(int argc, char *argv[]) { 
    struct sockaddr_in serv_addr; 
    int port_number, socket_fd; 
    port_number = atoi(argv[1]); 

    signal(SIGCHLD, sigchldAction); 

    if ((socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) exit(EXIT_FAILURE); 
    if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, 
(const void *)&optval, sizeof(int)) < 0) exit(EXIT_FAILURE); 

    bzero((void *)&serv_addr, sizeof(struct sockaddr_in)); 
    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
    serv_addr.sin_port = htons(port_number); 
    if (bind(socket_fd, (struct sockaddr *)&serv_addr, 
     sizeof(struct sockaddr_in)) < 0) exit(EXIT_FAILURE); 

    pid_t child_pid; 
    while (1) { 
    child_pid = fork(); 

    switch (child_pid) { 
     case -1: 
      perror("Fork() Failed. \n"); 
      exit(EXIT_FAILURE); 
      break; 
     case 0: 
      process_request(socket_fd); 
      exit(EXIT_SUCCESS); 
      break; 
     case 1: 
      close(socket_fd); 
      break; 

    } 

} 
    close(socket_fd); 
exit(EXIT_SUCCESS); 
} 

그럼 내 process_request 기능이 들어오는 데이터를 돌봐 :

void sigchldAction(int sig) { 
while (waitpid(-1, 0, WNOHANG) > 0) { 
    ; 
}int main(int argc, char *argv[]) { 

return; 
} //This is my function that waits for all the processes 

여기 내 서버입니다.

답변

4

UDP를 사용하고 있다면 연결되어 있지 않습니다. 그것은 연결없는 프로토콜입니다.

포크를 실행하려면 ftpd가 수행하는 작업을 수행하고 원격 클라이언트에게 원래의 포트와 다른 포트에서 분기 된 하위 패킷을 보내야한다고 말할 것입니다. 포트).

+0

그래서 udp에서는 모든 클라이언트를 동일한 수신 포트에서 실행시킬 수 없습니까? – fabricemarcelin

+2

@fabricemarcelin - 당신은 할 수 있지만 복잡해질 것입니다. recvfrom()을 사용하여 소스 주소 (클라이언트)를 가져 와서 그런 식으로 구분할 수 있습니다. 그러나 당신이 같은 포트에서 아이들을 포크한다면 첫 아이가 클라이언트 # 2의 초기 데이터 그램을 읽는 것을 막을 수 있습니까? accept()가 커버 아래에 새로운 소켓을 생성하기 때문에 TCP가이를 처리한다. – Duck

+0

@ 덕 - 빠른 질문. 소켓에서 분기하면 클라이언트에 매개 변수로 전달할 새 포트 번호를 어떻게 알 수 있습니까? – fabricemarcelin

1

fork()을 피하고 원본 주소를 기반으로 클라이언트를 구별하는 것이 좋습니다.

취할 수있는 기본 접근법은 현재 응용 프로그램 계층 연결 (예 : 현재 파일, 파일 내의 현재 위치, 클라이언트 주소)을 설명하는 변수를 모두 가져 와서이를 struct에 넣는 것입니다. 그런 다음 클라이언트 당 하나의 struct 인스턴스를 만듭니다.

들어오는 패킷을 수신 대기하려면 recv() 대신 recvfrom()을 사용하십시오. 이렇게하면 클라이언트의 주소가 제공됩니다 (이 주소는 클라이언트의 포트 번호를 포함해야 함). 그러면 클라이언트 당 적절한 인스턴스 인 struct을 찾을 수 있습니다.

+0

일부 의사 코드를 제공하거나 다음과 같은 예를 가리킬 수 있습니까? 감사 – m4n07