2010-06-02 5 views
2

안녕하세요 신사 숙녀 여러분, accept()에 약간의 문제가 있습니다. 나는 여러 대의 클라이언트와 하나의 서버를 가지고있다. 클라이언트는 서버와 연결하여 통신 할 수 있습니다. 그러나 한순간에 나는 서로에게 직접적으로 연결되는 클라이언트가 필요하며 거기에는 약간의 어려움이 있습니다. 클라이언트는 계속되는 스레드를 가지고 있습니다. 그 중 하나는 handle_connection()이고, 들어오는 연결은 listen()accept()으로 영원히 반복됩니다. while(1)이 있습니다. 클라이언트가 connect() 다른 클라이언트에 시도 할 때마다 connect()은 111 : Connection Refused라는 오류를 반환합니다. 올바른 IP 주소와 올바른 포트 (클라이언트 간 연결을 위해 포트를 지정했습니다)가 있음을 알고 있습니다. 연결을 기다리는 클라이언트는 새로운 연결이 없음을 알지 못합니다. 코드의 일부를 복사하여 누군가 내가 잘못하고있는 것을 지적 할 수 있기를 바랍니다. 모든 입력에 감사드립니다!C 소켓 : 클라이언트간에 connect() 및 accept()에 문제가 있습니다. 111 : Connection refused

이것은 모든 클라이언트 측 코드입니다. void * handle_connections(void * arg)은 들어오는 연결을 언제나 accept()으로 반복하는 스레드입니다. 내 서버는 매우 비슷한 thang을 가지고 있으며 매우 잘 작동합니다. (여기서 왜 작동하지 않는지 확실치 않습니다.) 이것은 새로운 들어오는 연결을 기다리는 클라이언트의 일부입니다. int handle_request(void * arg, struct message * msg)은 프로그램 중 한 지점에서 호출되며 struct message * msg에 지정된 클라이언트에 연결하려고 시도합니다.이 클라이언트에는 IP 주소와 포트 번호가 포함 된 struct sockaddr_in이 포함됩니다.

#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

고객이 방화벽을 사용하고 있습니까? –

+0

오늘날 가정용 네트워크를위한 라우터는 점점 더 보편화되고 있습니다. 대부분의 라우터는 라우터 설정에서 명시 적으로 구성되지 않은 인바운드 트래픽이 통과하는 것을 방지합니다. 라우터를 사용하지 않더라도 개인 방화벽은 드문 일이 아닙니다. 어쨌든, 클라이언트가 NAT/방화벽 뒤에 있다면, 그 클라이언트는 보통 다른 클라이언트에 연결할 클라이언트 여야합니다. 따라서 NAT/방화벽은 인바운드 클라이언트가 아닌 아웃 바운드 연결을 보게됩니다. 두 클라이언트가 모두 NAT/방화벽 뒤에있는 경우 두 클라이언트가 아웃 바운드를 연결하도록 서버를 통해 데이터를 프록시해야합니다. –

+0

글쎄, 클라이언트와 서버 모두 동일한 네트워크 내에 있지만 클라이언트는 서버에 잘 연결할 수 있습니다. 따라서 방화벽은 문제가되지 않을 것이라고 생각합니다. –

답변

2

귀하의 문제는 당신이 listen() 전에 bind()를 호출하지 않는, 그래서 당신은 무작위로 선택된 포트에 연결을 수신하는 것입니다, 아니 당신이 듣고 자하는 포트입니다.

당신이해야 할 다음 listen() 전에

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

. sockaddr 구조가 accept()에 전달하는 것이

참고 수신 할 주소가 아닌 - 그것은 accept()accept() 반환에 접속 한 클라이언트의 주소를 저장하기위한 출력 매개 변수입니다.

+0

다시 한번 감사드립니다. 나는 지금까지 바인드가 한 일을 이해했다고 생각하지 않는다. 하하. –

관련 문제