2010-06-02 68 views
2

你好,女士們,我有點問題accept()。我有多個客戶端和一臺服務器。客戶端可以很好地與服務器連接和通信。但有一點,我需要一些客戶直接相互連接,我在那裏遇到了一些困難。客戶端有一堆線程的事情,其中​​一人是handle_connection(),它有一個while(1),永遠循環,從而listen()accept()任何傳入連接。每當客戶端嘗試connect()到其他客戶端,connect()返回錯誤,111:連接拒絕。我知道我有正確的IP地址和正確的端口(我爲端到端客戶端連接指定了一個端口)。等待連接的客戶端沒有注意到任何事情,沒有新的連接,nada。我複製了部分代碼,希望有人能指出我做錯了什麼。感謝您的任何意見!C socket:連接()和/或客戶端之間的accept()問題。 111:拒絕接線

這是所有的客戶端代碼。 void * handle_connections(void * arg)是一個永久循環到accept()任何傳入連接的線程。我的服務器有一個非常類似的勝利,它工作得很好。 (不知道爲什麼它不能在這裏工作..)這是等待新的傳入連接的客戶端的一部分。 int handle_request(void * arg, struct message * msg)在程序期間調用在一個點,並嘗試連接到在struct message * msg包括struct sockaddr_in與IP地址和端口號和任何所指定的客戶端。

#define SERVER_PORT 10000 
#define CLIENT_PORT  3456 
#define MAX_CONNECTION 20 
#define MAX_MSG  50 

void * handle_connections(void * arg) 
{ 
    struct fd_info * info; 
    struct sockaddr_in client_address; 
    struct timeval timeout; 
    fd_set readset, copyset; 

    bzero((char *) &client_address, sizeof(client_address)); // copy zeroes into string 
    client_address.sin_family = AF_INET; 
    client_address.sin_addr.s_addr = htonl(INADDR_ANY); 
    client_address.sin_port = htons(CLIENT_PORT); 

    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    rv = listen(sockfd,MAX_CONNECTION); 


    while(1) 
    { 
     new_sockfd = accept(sockfd, (struct sockaddr *) &client_address, &client_addr_len); //blocks 

     if (new_sockfd < 0) { 
      printf("C: ERROR accept() %i: %s \n", errno, strerror(errno)); 
      sleep(2); 
     } else { 
      printf("C: accepted\n"); 
      FD_SET(new_sockfd, &readset); // sets bit for new_sockfd to list of sockets to watch out for 
      if (maxfd < new_sockfd) 
       maxfd = new_sockfd; 
      if (minfd > new_sockfd) 
       minfd = new_sockfd; 
     }  //end if else (new_sockfd) 

    } // end of the forever while loop 
} 

int handle_request(void * arg, struct message * msg) 
{ 
    char * cname, gname, payload; 
    char * command[3]; 

    int i, rv, sockfd, client_addr_len; 

    struct sockaddr_in client_address; 
    struct fd_info * info; 

    info = (struct fd_info *) arg; 
    sockfd = info->sock_fd; 


    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd == -1) 
    { 
     printf("HR: ERROR socket() %i: %s \n", errno, strerror(errno)); 
     break; 
    } 
    else if (sockfd > 0) 
    { 
     printf("HR: new socks is %i \n", sockfd); 
     printf("HR: sin_family is %i: %i\n", msg->peer.client_address.sin_family, msg->peer.client_address.sin_port); 
     //************************************************************* 
     //this is the part that returns error 111: Connection refused!!! 
     //************************************************************* 
     rv = connect(sockfd, (struct sockaddr *) &msg->peer.client_address, sizeof(struct sockaddr)); 
     if (rv == -1) 
     { 
      printf("HR: ERROR: connect() %i: %s \n", errno, strerror(errno)); 
      printf("HR: at %li \n", msg->peer.client_address.sin_addr.s_addr); 
      break; 
     } 
     else if (rv > 0) 
     { 
      info->max_fd = sockfd; 
      printf("HR: connected successfully!! \n"); 
     } 
    } 
} 
+0

您的客戶是否支持防火牆? – 2010-06-02 18:45:04

+0

家庭網絡的路由器現在越來越普遍。大多數路由器阻止未在路由器設置中明確配置的入站流量通過。即使沒有使用路由器,個人防火牆也並不少見。無論哪種方式,如果客戶端位於NAT /防火牆之後,那麼客戶端通常需要連接到其他客戶端,因此NAT /防火牆會看到出站連接而不是入站連接。如果兩個客戶端位於NAT /防火牆後面,則需要通過服務器代理數據,以便兩個客戶端都連接出站。 – 2010-06-02 19:00:25

+0

那麼,客戶端和服務器都在同一個網絡中,但客戶端可以很好地連接到服務器。所以我認爲防火牆不會是一個問題。 – 2010-06-02 19:29:45

回答

2

你的問題是,你是不是叫bind()listen()之前,所以你一個隨機選擇的端口上偵聽連接,不是你想監聽的端口。

您需要:

if (bind(sockfd, &client_address, sizeof client_address))) 
{ 
    perror("bind"); 
    /* Handle this error somehow */ 
} 
listen()

注意,sockaddr結構傳遞給accept()是不聽的地址 - 這是爲accept()以存儲已經連接時accept()返回客戶端的地址的輸出參數。

+0

再次感謝,隊友。我真的不認爲我理解到現在爲止綁定了什麼,哈哈...... – 2010-06-03 08:10:05

相關問題