2009-05-20 11 views
6

以下のサンプルコードは、サーバープロセスとして機能します。無効な引数 - 私はCソケットがエラーコード22を生成する、EINVAL - 無効な引数

struct sockaddr_in servaddr, clientaddr; 

以下の行

pid_t childpid; 

を追加するときしかし、それはエラーコード22、EINVALに沿っ

connectfd = accept(listenfd, (struct sockaddr *) &clientaddr, &clientaddrlen); 

で失敗します。私はCのソケットには新しく、問題を理解することができませんでした。このことについて教えてください。

ありがとうございました。

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <linux/in.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 

extern int errno; 

int main() 
{ 
    int clientaddrlen, listenfd, connectfd, bytes_rcvd, listen_queue_size=1; 
    short int port_no = 2000; 
    char buffer[1000]; 
    struct sockaddr_in servaddr, clientaddr; 

    printf("Server running at port #%d\n", port_no); 

    // Create server socket. 
    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
    { 
     fprintf(stderr, "Cannot create server socket! errno=%d \n", errno); 
     exit(-1); 
    } 
    printf("Server socket created\n"); 

    // Bind (attach) this process to the server socket. 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    servaddr.sin_port = htons(port_no); 
    bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)); 
    printf("Server socket is bound to port #%d\n", port_no); 

    // Turn 'listenfd' to a listening socket. Listen queue size is 1. 
    listen(listenfd,listen_queue_size); 
    printf("Server listening with a queue of size %d. \n", listen_queue_size); 

    // Wait for connection(s) from client(s). 
    while (1) 
    { 
     connectfd = accept(listenfd, (struct sockaddr *) &clientaddr, &clientaddrlen); 
     printf("A client has connected\n"); 
     if (recv(connectfd, buffer, sizeof(buffer), 0) > 0) 
      printf("Received message: %s\n", buffer); 
     close(connectfd); 
     printf("Server closed connection to client\n"); 
    } 

    close(listenfd); 
    return 0; 
} 
+3

Huh?未使用の変数宣言を追加するだけで、プログラムの動作が変わりますか?それは...間違いなく、間違った行を貼り付けましたか? – unwind

+1

また、このコードでは、タイトルにもかかわらずfork()を使用しません。 –

+0

実際、このような動作は非常に一般的です。スタックフレームのサイズが変わるため、バッファオーバーランなどの問題が発生する可能性があります。 –

答えて

11

clientaddrlenの初期化先が表示されません。これはイン/アウトのパラメータです。 accept()にアドレスのバッファーの大きさを教えてください。

+0

"clientaddrlen = sizeof((struct sockaddr *)&clientaddr);"という行を追加すると、トリックをしました。ありがとう! – emrekyv

4

未使用の変数宣言を追加すると、通常は受け入れが失敗しません。 Select is not broken

あなたが投稿したコードは、あなたが記述したとおりに動作できません。あなたはaccept()の戻り値をチェックしていないので、どのように失敗するのか分かりますか?エラーが発生しない限り、Unixシステム/ libcは通常を呼び出し、errnoはに設定されないので、accept()が-1を返さない限り、のerrnoには何かが含まれます。前記

  • ソケットが接続を監視されていません:あなたはそれを受け入れて確認した()が失敗して、errnoがEINVALに設定されている場合は、manページに応じて2つの可能性があります。
  • addrlenはは無効である(すなわち負)

EDIT(?あなたは聞いて()からの戻りコードを確認しました):最も重要なこと:をコンパイルし、あなたの問題を示し完全例を投稿してください。さもなければ、問題が何であるかを推測することしかできません。

+0

私が書いた別のコードでerrnoをチェックしました。これは単純なものです。私は誤った情報をお詫びします。 listen()は0を返します。しかし、clientaddrlenは否定的です。何が原因なの? – emrekyv

+0

方向をありがとうございました。私はaccept()のmanページをチェックして、 "addrlen引数は値の結果の引数です:最初はaddrが指し示す構造体のサイズを含んでいなければなりません。返されたアドレスの長さ(バイト単位)。私はclientaddrlenを初期化し、問題を解決しました! まだ変数を宣言するとaccept()が失敗する理由はわかりません。私はバグは期待していませんが、どうして失敗するのかを知りたいのです。ありがとう! – emrekyv

+0

@Neilがコメントしたように、変数を追加すると、スタックレイアウトがclientaddrlenに変更され、実際には負ではない値に初期化され、accept()によって受け入れられます。それにもかかわらず、それはジャンクです。 – JesperE

関連する問題