2011-12-04 3 views
0

以下のコードでは、3つの機能(mainを含む)があります。 receive_loop関数は127.0.0.1にバインドされたソケットをポーリングし、メッセージを受け取った場合はそれを出力します。 sender_loopscanfを使用してユーザー入力を待機し、入力がある場合は127.0.0.1にバインドされたソケットを介して送信します。 mainは、子供にsender_loopをフォークして実行し、親にはreceive_loopを実行します。メッセージを受信するメッセージングアプリケーションの1つのインスタンス

コードをコンパイルしてこの実行可能ファイルの2つのインスタンスを実行すると、いずれかのインスタンスが起動するどちらのインスタンスからでも最初に送信されたメッセージが受信されます。つまり、まずinstance1が起動された後、instance1はinstance1とinstance2によって送信されたメッセージを受信します。私はなぜこれが起こっているのか分かりません。誰かがそれを説明できるかどうか分かります(詳細)。ありがとう。

// INCLUDES NOT SHOWN 

// recieve_loop 
int receive_loop(int sock_fd, struct sockaddr *peer) { 
    int isDataReady = 0; 
    char buff[128] = {0}; 
    struct pollfd poll_struct; 

    poll_struct.fd  = sock_fd; 
    poll_struct.events = POLLIN; 

    printf("reciever up\n"); 
    while (1) { 
     while (1) { 
      if (isDataReady > 0) break; 
      isDataReady = poll(&poll_struct, 1, 500); 
     } 
     socklen_t sock_len = sizeof(struct sockaddr); 
     recvfrom(sock_fd, 
       buff, 
       sizeof(buff), 
       0, 
       (struct sockaddr *)peer, 
       &sock_len); 

     printf("%s\n", buff); 
    } 

    return 0; 
} 


// sender_loop 
int sender_loop(int sock_fd, struct sockaddr *peer) { 
    char buff[32] = {0}; 

    printf("sender up\n"); 
    while (1) { 
     scanf("%s", buff); 

     int bytes_sent = sendto(sock_fd, buff, sizeof(buff), 0, (struct sockaddr *)peer, sizeof(struct sockaddr_in)); 

     if (bytes_sent <= 0) 
      printf("sending message failed\n"); 

    } 

    return 0; 
} 

int main(int argc, const char *argv[]) { 
    // socket file descriptor to send data through 
    int sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 

    // fill in the peer's address, loopback in this case 
    struct sockaddr_in *peer = malloc(sizeof(struct sockaddr_in)); 
    peer->sin_family = AF_INET; 
    peer->sin_port = htons(11110); 
    inet_pton(AF_INET, "127.0.0.1", &peer->sin_addr); 

    bind(sock_fd, (struct sockaddr *)peer, sizeof(struct sockaddr_in)); 

    pid_t pid = fork(); 
    if (pid < 0) { 
     printf("Couldn't fork, exiting"); 
     return 1; 
    } 
    if (pid == 0) { 
     sender_loop(sock_fd, (struct sockaddr *)peer); 
    } else { 
     receive_loop(sock_fd, (struct sockaddr *)peer); 
    } 
    return 0; 
} 

答えて

2

最初のインスタンスによってすでに使用中のポートにバインドしようとしているので、あなたの2番目のインスタンスがbind()に失敗しています。

これに変更してご覧ください。

int ret = bind(sock_fd, (struct sockaddr *)peer, sizeof(struct sockaddr_in)); 
if (ret < 0) 
{ 
    perror("bind"); 
    exit(1); 
} 
+0

しかし、なぜ2番目のインスタンスはまだメッセージを送信できますか?それは、メッセージを正しく受け取ったり、受け取ったりすることができないはずです。 – mtahmed

+0

bindを呼び出す前に、setsocktoptでSO_REUSEADDR設定を使用して、バインドが失敗しないようにすることもできます。両方のインスタンスが実行されます。着信パケットが到着すると、インスタンスの1つがパケットを処理します。 SOCK_DGRAM(UDP)では、特定のホストから送信されたパケットが同じプログラムインスタンスによって処理されることは間違いありません。 – selbie

+0

@mtahmed - UDPソケットは特定のポートにバインドされていない場合でも "送信"できます。 OSはソースポートとして使用されていないランダムな値を選択します。 – selbie

関連する問題