2012-03-11 7 views
0

私は多くのクライアントに役立つサーバを構築しようとしています。Linuxソケットプログラミングで不思議なことが起こった

サーバーは簡単な作業を行います。クライアントからの入力文字列を取得し、各文字を大文字に変更します。

しかし、問題は、たとえば「Ctrl-C」とタイプしているクライアントをシャットダウンしようとすると、OSが突然シャットダウンします。

私はUbuntu 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

Er、*** OS ***がシャットダウンしますか?それはあなたに何かメッセージを与えていますか? –

+0

適切な字下げがないと、コードは必要以上に読みにくくなります。 –

+0

OSは停止しましたが、何もできませんが、コンピュータをシャットダウンします – KUN

答えて

6

お使いのサーバーのコードは、フォーク爆弾を引き起こしている、とあなたはacceptの戻り値をチェックしていないので、あなたが正しくそれを見ていません。

根本的な原因は、接続が閉じられた後にクライアントに読み書きする場合、exitを呼び出すことも、メインから返さないことです。

子プロセスがトップレベルのwhile(1)ループにとどまり、listenfdにあるacceptにしようとしましたが、それは正常です。 acceptが失敗し、あなたはフォークに関係なくフォークします。フォークのタイトループはコンピュータの速度を落としますが、スケジューラは適切な対策を講じることはできません。

close(connfd)の後にプログラムを終了し、コードにエラーチェックを追加します。

+0

ありがとうございます。あなたは本当に良い答えです – KUN

関連する問題