2016-08-29 2 views
4

UDP 서버가 select 시스템 호출로 패킷을 수신 중입니다. 그리고 각 UDP 클라이언트로부터 최신 패킷을 받고 싶습니다. (또한 여러 개의 UDP 클라이언트 패킷을 듣고 싶습니다.) 내 간단한 UDP 서버의udp 서버의 최신 패킷 수신 - C

코드 :

int main(void) { 
    int fd; 
    int port = 5678; 
    char buffer[1024]; 
    fd_set readfs; 
    socklen_t client_length; 
    struct timeval timeout_interval; 
    struct sockaddr_in6 server_addr; 
    struct sockaddr_in6 client_addr; 
    int result; 
    int recv; 
    char client_addr_ipv6[100]; 

    fd = socket(PF_INET6, SOCK_DGRAM, 0); 
    printf(" \e[1m \e[34m ---------------------------------------- \n-------------------- UDP SERVER --------------------\n \e[39m \e[0m \n"); 
    printf("Process: \e[34m %d \e[49m Port ..\n", port); 

    if (fd < 0) { 
     printf("ERR: fd < 0"); 
    } else { 
     memset(&server_addr, 0, sizeof(server_addr)); 
     server_addr.sin6_family = AF_INET6; 
     server_addr.sin6_addr = in6addr_any; 
     server_addr.sin6_port = htons(port); 
     memset(&client_addr, 0, sizeof(client_addr)); 
     client_addr.sin6_family = AF_INET6; 
     client_addr.sin6_addr = in6addr_any; 
     client_addr.sin6_port = htons(port); 

     if (bind(fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) 
       >= 0) { 
      printf("\e[1m INFO: \e[0m \e[34m Bind success.. \e[39m\n"); 

     } else { 
      printf("Bind."); 
      return -1; 
     } 
     for (;;) { 
      FD_ZERO(&readfs); 
      FD_SET(fd, &readfs); 
      int max_fd = MAX(0, fd); 
      timeout_interval.tv_sec = 3; 
      timeout_interval.tv_usec = 50000000; 

      result = select(max_fd + 1, &readfs, NULL, NULL, &timeout_interval); 
      //printf("\n %d \t %d \n", result, fd); 
      if (result < 0) { 
       printf("ERR\n"); 
      } else if (result == 0) { 
       printf("\nTimeout\n"); 
      } else { 
       if (FD_ISSET(fd, &readfs)) { 
        client_length = sizeof(client_addr); 
        if ((recv = recvfrom(fd, buffer, sizeof(buffer), 0, 
            (struct sockaddr *) &client_addr, &client_length)) 
          < 0) { 
         printf("Recv-ERR!"); 
         break; 
        } 
        inet_ntop(AF_INET6, &(client_addr.sin6_addr), client_addr_ipv6, 100); 
        //printf("Client IP/Port : %s ",client_addr_ipv6); 

        printf("\n ------------------------------------------ \n"); 
        printf("\e[1m Data: \e[0m \e[32m %.*s \n Client IP/Port : \e[34m %s/%d \n\e[39m", recv, buffer,client_addr_ipv6,ntohs(client_addr.sin6_port)); 
       } 
      } 
     } 
    } 
} 
+1

다른 서버에서 보낸 마지막 패킷을 의미한다고 가정하면 UDP 패킷의 순서가 정해져 있지 않으므로 마지막으로 보낸 패킷을 알 수 없습니다. 어느 것이 "마지막"인지 결정하기 위해 패킷에 데이터를 넣어야합니다. –

+0

각 udp-client에서 마지막으로 오는 패킷을 의미합니다. 그래서 어떻게 패킷에서 "마지막"정의하지 않고 할 수 있습니다. 내가 "이 udp 클라이언트에서 가장 최근의 패킷"같은 코드 수 있습니까? 또는 어떻게 이런 식으로 코드 수 있습니까? – Gkan

+0

패킷이 "최신"인지 어떻게 알 수 있습니까? – dbush

답변

1

이 처리하는 가장 좋은 방법은 보낸 사람이하는 것입니다 각 패킷에 일련 번호를 넣습니다. 전송 된 각 패킷에 대해 시퀀스 번호가 1 씩 증가합니다.

수신 측에서는 수신 한 마지막 패킷의 카운터를 추적합니다. 들어오는 다음 패킷이 더 큰 카운터를 가지고 있으면 최신 패킷입니다. 크기가 크지 않은 경우 이전 패킷이므로 응용 프로그램에 적절한 방식으로 처리 할 수 ​​있습니다.

또한 recv 변수의 이름을 recv_len으로 바꿔야합니다. recv은이 변수 정의에 의해 마스크 될 소켓 함수의 이름입니다.

+0

의미가 있지만, 가장 오래된 패킷은 중요하지 않으므로 패킷을 카운트하거나 시퀀싱하지 않고 수행하고 싶습니다. 분명히 나는 ​​의미한다. 가장 오래된 패킷은 중요하지 않으며 마지막 패킷을 처리하는 데 사용하고 싶습니다. 또한 내가 패킷을 수신 후 udp 서버 기능의 일부 프로세스가 다음 버퍼가 같은 시간에 다른 패킷을 수신 대기합니다. 따라서 내 프로세스가 서버를 끝내면 다음 패킷 (버퍼에서)을 계속 처리하십시오. 프로세스가 끝나면 버퍼가 깨끗해야합니다 (어떤 클라이언트가이 패킷을 보내야하는지 확인해야합니다). 각 클라이언트의 버퍼에있는 최신 패킷이어야합니다. – Gkan

+0

@ GökhanAyrancıoğlu 로컬 버퍼를 모두 플러시하지 않고도 버퍼의 마지막 패킷 만 가져올 수는 없습니다. 두 번 연속해서 읽는다면 읽은 첫 번째 패킷이 그 자체로 버퍼에 있는지 또는 다른 패킷이 뒤에 있는지 알 수 없습니다. 당신은 단지 그것을 계속 읽을 필요가 있습니다. 그리고 패킷이 잘못 도착하면 패킷에 패킷이 있어야 그 사실을 알 수 있습니다. – dbush

+0

의견을 보내 주셔서 감사합니다. 사실 나는 각 패킷에 대해 동일한 패킷 크기와 형식을 작성해야합니다. 그래서 나는 당신이 말한대로 그들 모두를 읽으려고 노력할 것입니다. 그런 다음이 크기로 버퍼를 분할하여 가장 최근의 방법으로 찾을 수 있습니다. 도와 줘서 고마워. – Gkan