2016-05-25 57 views
0

クライアントがサーバーから文字列を受け取り、次のクライアント接続に配信される新しいメッセージを送信する単純なチャットアプリケーションを作成しようとしています。私はソケットプログラミングを初めて勉強しています。なぜこのエラーが発生するのか理解できません。クライアントがバッファを送信した後、サーバはaccept()(-1を返す)と不正なファイル記述子でエラーを通知します。ここでは、サーバー上で実行されているコードは次のとおりです。不正なファイル記述子:accept()でエラーが発生しました

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

void error(char *msg) { 
    perror(msg); 
    exit(1); 
} 

int main (int argc, char *argv[]) { 

    if (argc < 2) { 
     error("ERROR, no port provided\n"); 
    } 

    int sockfd; 
    struct sockaddr_in serv_addr, cli_addr; 
    int cli_len, portno; 
    char message[256]; 
    pid_t pid; 
    int n; 

    portno = atoi(argv[1]); 
    bzero((char*)&serv_addr, sizeof(serv_addr)); 
    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_addr.s_addr = INADDR_ANY; 
    serv_addr.sin_port = htons(portno); 

    sockfd = socket(AF_INET, SOCK_STREAM, 0); 

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

    listen(sockfd, 5); 

    do { 
     cli_len = sizeof(cli_addr); 

     int newsockfd; 
     newsockfd = accept(sockfd,(struct sockaddr*)&cli_addr,(socklen_t *)&cli_len); 
     if (newsockfd < 0) { 
      printf("%i", newsockfd); 
      error("ERROR on accept\n"); 

     } 

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

      close(sockfd); 
      sockfd = -1; 

      n = send(newsockfd, message, strlen(message), 0); 
      if (n < 0) error("ERROR sending\n"); 

      bzero(message, 256); 

      n = recv(newsockfd, message, 256, 0); 
      if (n < 0) error("ERROR receiving\n"); 

      close(newsockfd); 
      newsockfd = -1; 

     } 

    } 
    while(1); 

    return 0; 
} 
+2

cli_lenは、int型ではなく、socklen_t型である必要があります。型キャストはx86_64の潜在的な問題を隠しています。intは32ビットですが、他のsize_related型は64ビットです。 –

+1

エラーを正しく報告していません。 'printr()'のように 'errno'を変更することができるようにするには、' perror() 'や' strerror() '*を呼び出す必要があります。修正、再テスト、... – EJP

+2

問題2、子は終了したらexitを呼び出す必要があります。そうしないと、子と親の両方がaccept();-)で戦います。 –

答えて

1

子どもは、read()の後に終了する必要がありますが、それは終了しません。それはループを続けます。おそらくあなたの意図ではないでしょうか。

次に、accept()を呼び出し、-1をソケット記述子として渡します。 -1は有効なソケット記述子ではありません。失われ、上書きされますsocket()で返されるので、有効なソケット記述子を行う

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

     close(sockfd); 
     sockfd = -1; 

accept(sockfd, ... 

子供がsockfdここ-1に設定します。

したがって、観察しているエラーは、リスニングサーバープロセスではなく、フォークオフした子プロセスから発生します。

 ... 
     newsockfd = -1; 
     exit(EXIT_SUCCESS); 
     } 

このint cli_len;socklen_t cli_len;次のようになります。これは、このように、子の内側にexit()への呼び出しを追加する修正するには

。そして、cli_lenのキャストはaccept()を呼び出すときに削除する必要があります。 はありません。盲目的にエラーをキャストしてください!

2

fork()の結果は、あなたが受け入れられたソケットであなたのI/Oを行い、その後、プロセスを終了する必要がゼロである場合。現在のところ、リスニングソケットを閉じた後に、子プロセスでacceptループを再実行できるようにしています。

関連する問題