2011-12-04 167 views
0

在下面的代碼我有3個功能(包括main)只有一個實例。 receive_loop功能輪詢綁定到127.0.0.1的套接字,如果它獲得任何消息,它將打印它。使用scanf並且當存在一個輸入時,它發送其通過結合至127.0.0.1套接字sender_loop等待用戶輸入。該main叉子和運行sender_loop在孩子和家長receive_loop消息收發應用程序接收消息

現在,如果我編譯代碼並運行此可執行文件的兩個實例,取其實例啓動時首先接收這兩種情況下發送的消息。因此可以說,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

你的第二個實例上bind()失敗,因爲它試圖綁定到一個端口已經在通過初審的使用。

切換到這一點,看看。

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

但爲什麼是第二個實例仍然可以發送郵件?它不應該能夠接收或發送正確的消息? – mtahmed

+0

在調用綁定之前,您還可以使用setsocktopt的SO_REUSEADDR設置來避免綁定失敗。你的程序的兩個實例都會運行。當進入的數據包進入時,其中一個實例將處理數據包。對於SOCK_DGRAM(UDP),您絕對不能保證從特定主機發送的數據包將由相同的程序實例處理。 – selbie

+0

@mtahmed - 如果UDP套接字未綁定到特定端口,則仍然允許「發送」。操作系統會選擇一個隨機的未使用的值作爲源端口。 – selbie