2011-12-04 125 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