2013-07-23 2 views
0

모든 인터페이스에서 IPv4 및 IPv6을 모두 허용하는 서버를 만들고 싶습니다.다중 클라이언트 서버, 다중 인터페이스, 다중 IP 버전 소켓

localhost, 127.0.0.1, :: 1, 192.168.1.26을 포함한 모든 주소에서 작동하지 않는 것 같습니다. 내가 무엇이 누락 되었습니까?

getaddrinfo(3)에 따르면, ai_family가 AI_PASSIVE 플래그로 설정되기 때문에. 여기에 지금까지 내 코드입니다

'반환 소켓 주소는 "와일드 카드 주소를"포함됩니다'.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <sys/types.h> 
#include <sys/times.h> 
#include <errno.h> 


#define MAXBUF 1024 

const char* PORTNUM = "687"; 

int init_address(struct addrinfo* hints) 
{ 
    hints->ai_flags=  AI_PASSIVE; 
    hints->ai_family= AF_UNSPEC; 
    hints->ai_socktype= SOCK_DGRAM; 
    hints->ai_protocol= IPPROTO_UDP; 
    return 1; 
} 

socklen_t init_socket(struct addrinfo* res, int* sockfd) 
{ 
    struct addrinfo* ressave; 
    struct sockaddr_in* all_interface; 
    socklen_t addrlength; 

    ressave=res; 
    all_interface = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in)); 

    do {/* each of the returned IP address is tried*/ 
     (*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 
     if ((*sockfd)<0) 
      continue; /* fail, try next one*/ 

     if (bind((*sockfd), (struct sockaddr*)all_interface, sizeof(all_interface)) == 0) 
      break; /*success*/ 

     close(*sockfd); 

    }while(res->ai_next != NULL && (res = res->ai_next)!= NULL); 

    if(&addrlength) 
     addrlength = res->ai_addrlen; 

    freeaddrinfo(ressave); 
    free(all_interface); 

    return addrlength; 
} 

int doprocessing(char* buffer, size_t buff_size) 
{ 
    return 0; 
} 

int peak_data(char* buffer, size_t buff_size) 
{ 
    return 0; 
} 

int main(int argc, char const *argv[]) 
{ 
    int sockfd, newsockfd; 
    int bytes_read; 
    char* port; 
    char buffer[MAXBUF]; 
    pid_t pid; 
    socklen_t addrlen, len; 
    struct addrinfo* socket_info; 
    struct addrinfo* res; 
    struct addrinfo* backup_res; 
    struct sockaddr* cliaddr; 
    int n; 

    socket_info = (struct addrinfo*)malloc(sizeof(struct addrinfo)); 
    res = (struct addrinfo*)malloc(sizeof(struct addrinfo)); 

    memset(socket_info, 0, sizeof(struct addrinfo)); 
    init_address(socket_info); 


    if((n = getaddrinfo(NULL, PORTNUM, socket_info, &res)) !=0) 
    { 
     printf("multi_server: error for %s: %s", PORTNUM, gai_strerror(n)); 
     exit(0); 
    } 

    if ((addrlen = init_socket(res, &sockfd)) < 0) 
    { 
     printf("multi_server: Socket or Bind error"); 
     exit(0); 
    } 

    free(socket_info); 

    cliaddr=malloc(addrlen); 

    len=addrlen; 

    printf("\nUDP Server: waiting for connection..."); 
    while (1) { 
     bytes_read = recvfrom(sockfd, buffer, MAXBUF-1, MSG_PEEK, cliaddr, &len); 

     if (bytes_read > 0) { 
      // a connection has been established 
      buffer[MAXBUF] = '\0'; 
      printf("\nUDP Server: received %d bytes ", bytes_read); 
      pid = fork(); 

      if (pid < 0) { 
       perror("UDP Server: ERROR while forking new process.\n"); 
       exit(1); 
      } 
      // check if the process ID is zero 
      if (pid == 0) { 
       // we are now inside the new forked process 
       if(peak_data(buffer, bytes_read)) 
       { 
        doprocessing(buffer, bytes_read); 
       } 
       printf("Now in %d\n", pid); 
       close(sockfd); 
       exit(0); 
      } 
     } 
    } 
} 

답변

1

아무 것도 없습니다. 그것은 당신이 말한 연결을 수락하고 있습니까? 그런 다음 ipv6 연결을 수락합니다. 그리고 IPv6는 하위 호환이기 때문에 올바른 ipv6 소켓을 만들었 으면 ipv4 패킷도 보내고받을 수 있어야합니다.

+0

IPV6_V6ONLY 모드를 비활성화하고 IPv6을 허용하려면 Windows에서 setsockopt (my_sock, IPPROTO_IPV6, IPV6_V6ONLY, &val); (여기서 val은 0 값의 정수 변수))를 수행해야합니다. 소켓도 IPv4 연결로 작동합니다. –

+0

죄송합니다. 작동하지 않는 것을 의미합니다. – GeneralZero

+0

@JeremyFriesner는 방화벽을 해제하고 낮은 포트 번호부터 루트로 실행하는 것을 잊어 버렸습니다. – GeneralZero

관련 문제