2017-04-05 135 views
0

我試圖連接到從其他遠程設備製作的本地UNIX服務器。服務器啓動並收聽我指定的端口。我還添加了一個新的防火牆規則來打開該端口,但我的客戶端仍然無法連接。它顯示錯誤連接被拒絕甚至在添加新的防火牆規則後仍拒絕連接

這裏是我的服務器代碼

int main() { 
    int fd, i,svclient,rval,msg; 
    int clients[10], num_clients; 
    fd_set read_set,write_set; 
    char buf[100]; 

    struct sockaddr_in addr; 

    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 
    perror("socket error"); 
    exit(-1); 
    } 


    bzero((char *) &addr, sizeof(addr)); 
    addr.sin_family = AF_INET; 
    addr.sin_addr.s_addr = INADDR_ANY; 
    addr.sin_port = htons(4001); 

    //strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1); 
    //strcpy(addr.sun_path, NAME); 

    if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { 
    perror("bind error"); 
    exit(-1); 
    } 
    printf("Bind complet...\n"); 

    if (listen(fd, 20) == -1) { 
    perror("listen error"); 
    exit(-1); 
    } 

    num_clients = 0; 
    int size = sizeof(fd); 

    while (1) { 

    int clientfd; 
    struct sockaddr_in client_addr; 
    int addrlen=sizeof(client_addr); 
    FD_ZERO(&read_set); 
    FD_SET(fd, &read_set); 

    for (i = 0; i < num_clients; i++) { //at first this part will not excute 
     FD_SET(clients[i], &read_set); 
    } 

    select(fd + num_clients + 1, &read_set, NULL, NULL, NULL); 


    if (FD_ISSET(fd, &read_set)) { 
     if ((clients[num_clients++] = accept(fd,(struct sockaddr*)&client_addr,&addrlen)) == -1) { 
     perror("accept error"); 
     continue; 
     } 
     /*printf("incoming message..................... !\n \n");*/ 
     printf("%s:%d connected\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); 
    } 


    for (i = 0; i < num_clients; i++) { 

     if (FD_ISSET(clients[i], &read_set)) { 
     msg = read(clients[i], buf, sizeof(buf)); 
     if(msg > 0){ 
      buf[msg] = 0; 
      int savedclnt = clients[i]; 
      printf("%s \n \n", buf); 

      /*for(int p=0;p<num_clients;p++) 
      { 
      if(clients[p]!= savedclnt){ 
       write(clients[p],buf,msg); 
      } 

      }*/ 
     } 

     } 

    } 
    } 
} 

和我的客戶

int main() 
{ 

    struct uci_context *uci; 
    uci = uci_init(); 
    int sockfd; 
    int ret; 
    struct sockaddr_in dest; 
    struct addrinfo hint, *res = NULL; 
    struct hostent *host; 
    char *hostip; 
    char *string; 



    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
    { 
     puts("Unble to create socket"); 
     exit(1); 
    } 

    hostip = ucix_get_option(uci, "pack_mon", "pack_monitoring", "address"); 
    string = ucix_get_option(uci, "pack_mon", "pack_monitoring", "port"); 

    bzero(&dest, sizeof(dest)); 
    dest.sin_family = AF_INET; 
    dest.sin_port = htons(atoi(string)); 

    memset(&hint, '\0', sizeof hint); 
    hint.ai_family = PF_UNSPEC; 
    hint.ai_flags = AI_NUMERICHOST; 

    printf(" %s- %s\n", hostip, string); 



    if(isdigit(hostip[0])){ 
     ret = getaddrinfo(hostip, NULL, &hint, &res);// this is more efficient than inet_addr 

     if (ret) { 

      exit(1); 
     } 
    }else if((host = gethostbyname(hostip)) != 0){ 

     memcpy((char*)&dest.sin_addr , (char*)host->h_addr , (sizeof dest.sin_addr)+1); 

    }else{ 

     exit(1); 
     printf("cannot resolve ip address"); 
    } 


    if (connect(sockfd, (struct sockaddr *)&dest, sizeof(dest)) < 0) 
    { 

     perror("ERROR Connecting"); 
     exit(1); 
    }else{ 

     printf("Port number %s is open.....\n",string); 
    } 


    char *message; 
    message = "help"; 
    write(sockfd,message,strlen(message)); 


    close(sockfd); 
    freeaddrinfo(res); 
    return 0; 
} 

防火牆規則

須藤的iptables -I INPUT -p根據tcp --dport 4001 - j ACCEPT

錯誤是:

192.168.10.155- 4001

ERROR連接:連接被拒絕

和這個日誌從該代碼來:

的printf( 「%S-%S \ n」 個,主機IP,字符串) ;

perror(「ERROR Connecting」);

exit(1);

+0

如果你想檢查'errno'(直接或間接通過例如'perror'),你需要在失敗函數後立即執行。如果你使用任何可能設置'errno'的函數(printf'可能會間接執行),那麼errno的值是未定義的。 –

+0

首先,您確定防火牆已打開嗎?在規則之前可能有其他規則阻止了這一點?確保一種方法(也許你是iptables的專家,但只是爲了確保..),就是在該端口上設置其他內容並進行測試。如果這樣的話你確定問題出在你的代碼中。自從您添加了防火牆規則後,我只會提起它,聽起來問題可能出現在代碼中或代碼中。設置netcat「webserver」是測試的一種方法。運行:netcat -l 5001 MrApnea

+0

至於你的問題,如果'hostip [0]'是一個數字,在註釋的代碼,那麼你不會設置'dest.sin_addr'。假設你假設'hostip'是一個IP地址,那麼你不需要爲'getaddrinfo'調用。只需使用['inet_pton'](http://man7.org/linux/man-pages/man3/inet_pton.3.html)。另外,在另一種情況下,你不應該真的使用'strncpy',因爲數據並不是一個字符串。 –

回答

0

您的客戶端沒有指定要連接的IP地址的代碼。所有可以做到的代碼都被註釋掉了。

更新:現在你的錯誤是在這裏:

strncpy((char*)&dest.sin_addr , (char*)host->h_addr , sizeof dest.sin_addr); 

strncpy功能僅適用於C風格的字符串。您需要使用memcpy或類似的東西。如果除了最後一個字節(網絡字節順序)以外的任何八位字節爲零,這將只複製部分IP地址。

更新:現在你的錯誤是在這裏:

printf("%d\n", connect(sockfd, (struct sockaddr *)&dest, sizeof(dest)) < 0); 
    perror("hmmmm"); 
    exit(1); 

這就要求connect,然後調用printf,然後調用perror。問題是,即使成功,printf的調用也可以修改errno。因此,您撥打perror可以打印完全不相關的錯誤消息。

+0

這不是問題,我可以連接到我的設備的其他端口像80甚至谷歌的IP和端口,但不能連接在這個特定的端口5001. –

+0

@johnleonardonwuzuruigbo它是如何遵循觀察到這不是問題?在這種特殊情況下(現在忘記其他情況),您如何看待操作系統知道客戶端嘗試連接的IP地址?如果操作系統不知道你想要訪問什麼IP地址,你怎麼能期待它的工作? –

+0

@johnleonardonwuzuruigbo舉一個比喻:假設你走過街道時沒有看到兩條路,並被汽車撞到。你會說:「這不可能是因爲我沒有看到兩種方式,在穿過起居室之前我沒有看到兩路,也沒有被汽車撞到。我的草坪,並沒有被汽車撞到。「 –