2012-03-11 4 views
0

많은 클라이언트를 지원할 수있는 서버를 구축하려고합니다.리눅스 소켓 프로그래밍에 이상한 일이 발생했습니다.

서버는 간단한 작업 만 수행합니다. 클라이언트에서 입력 문자열을 가져온 다음 각 문자를 대문자로 변경하십시오.

그러나 한 클라이언트 (예 : "Ctrl-C")를 종료 할 때 문제가 발생하면 OS가 갑자기 종료됩니다.

필자는 우분투 10.10 및 CentOS를 사용하여 프로그램을 테스트하지만 항상 동일한 문제가 발생합니다. 여기 내 소스 코드입니다 : 귀하의 서버 코드는 포크 폭탄을 일으키는

/* client.c */ 
#include <stdio.h> 
#include <signal.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#define MAXLINE 80 
#define SERV_PORT 8000 

int main (void) 
{ 
    struct sockaddr_in servaddr, cliaddr; 
    char buf[MAXLINE]; 
    int sockfd, n; 

    sockfd = socket(AF_INET, SOCK_STREAM, 0); 

    bzero(&servaddr, sizeof(servaddr)); 
    servaddr.sin_family = AF_INET; 
    inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr); 
    servaddr.sin_port = htons(SERV_PORT); 

    connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); 

    while (fgets(buf, MAXLINE, stdin) != NULL) { 
     write(sockfd, buf, strlen(buf)); 
     n = read(sockfd, buf, MAXLINE); 
     if(n == 0) printf("Connect closed\n"); 
     else write(STDOUT_FILENO, buf, n); 
    } 
    close(sockfd); 
    return 0; 
} 

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

#define MAXLINE 80 
#define SERV_PORT 8000 

void sigchld_func (int signo) { 
    wait(NULL); 
} 

int main (void) 
{ 
    struct sockaddr_in servaddr, cliaddr; 
    char buf[MAXLINE]; 
    char str[INET_ADDRSTRLEN]; 
    int  listenfd, connfd; 
    socklen_t cliaddr_len; 
    int  n, i; 
    pid_t pid; 

    signal(SIGCHLD, sigchld_func); 

    listenfd = socket(AF_INET, SOCK_STREAM, 0); 

    bzero(&servaddr, sizeof(servaddr)); 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    servaddr.sin_port = htons(SERV_PORT); 

    bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); 

    listen(listenfd, 20); 

    printf("Accepting connections...\n"); 

    while (1) { 
     cliaddr_len = sizeof(cliaddr); 
     connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); 
     if ((pid = fork()) < 0) { 
      perror("fork error!"); 
      exit(1); 
     } else if (pid > 0) { 
      close(connfd); 
     } else { 
      close(listenfd); 
      while (1) { 
       n = read(connfd, buf, MAXLINE); 
       if (n <= 0) { 
        printf("Connection closed\n"); 
        break; 
       } 
       inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)); 
       printf("Received from %s at port %d\n", str, ntohs(cliaddr.sin_port)); 
       for (i = 0; i < n; i++) 
        buf[i] = toupper(buf[i]); 
       write(connfd, buf, n); 
      } 
      close(connfd); 
     } 
    } 
    return 0; 
} 
+5

어, *** OS ***가 종료됩니까? 그것은 당신에게 어떤 메시지를주고 있습니까? –

+0

들여 쓰기가 적절하지 않으면 코드가 필요한 것보다 훨씬 더 읽기가 어렵습니다. –

+0

죄송합니다 .. OS가 정지되었습니다. 아무 것도 할 수 없지만 컴퓨터를 종료 할 수 있습니다. – KUN

답변

6

, 당신은 accept의 반환 값을 확인하지 있기 때문에 당신이 제대로 표시되지 않는.

근본 원인은 연결을 닫은 후에 클라이언트에 읽거나 쓰는 자식에서 exit을 호출하거나 주 밖으로 나간 것이 아니라는 것입니다.

그래서 하위 프로세스는 최상위에있는 while(1) 루프에 머물러 listenfdaccept을 시도합니다 (그러나 그 중 하나는 좋음). accept이 실패하고 포크에 관계없이 포크합니다. 포크의 단단한 고리는 컴퓨터 속도를 늦추고, 스케줄러는 적절히 대처할 수 없습니다 (대책이없는 한).

close(connfd) 이후 프로그램을 종료하고 코드에 오류 검사를 추가하십시오.

+0

고맙습니다. 당신은 대답 정말 좋습니다 – KUN

관련 문제