2013-03-24 4 views
4

부스트 : asio 문서 (비동기 클라이언트에서 자동으로 나타남)를 읽었으며 여기를 살펴 보았지만 여기에서 나무에 대한 포리스트를 찾을 수 없습니다.부스트 비동기 UDP 클라이언트

나는이처럼 보이는 메인 루프가 시뮬레이션있어 : 충분히

for(;;) 
{ 
    a = do_stuff1(); 
    do_stuff2(a); 
} 

쉬운. 내가 가질 수 있도록 내가하고 싶은 무엇

, 수정할 수 있습니다 :

나는 다음과 같은 요구 사항이
for(;;) 
{ 
    a = do_stuff1(); 
    check_for_new_received_udp_data(&b); 
    modify_a_with_data_from_b(a,b); 
    do_stuff2(a); 
} 

:

내가 아니었다해서 데이터를 잃을 수 없습니다
    1. 적극적으로 듣는다. IE 서버가 패킷을 보낸 시간에 check_for_new_received_udp_data() 대신 do_stuff2()에 있었기 때문에 패킷을 잃고 싶지 않습니다.
    2. 주 for for 루프가 60Hz에서 실행되어야하므로 check_for_new_received_udp_data() 블록을 약 2ms 이상 가질 수 없습니다.
    3. 서버가 다른 곳에서 실행되며 완전히 일정이 잘못되었습니다. 때로는 데이터가 없으며, 반복적으로 같은 패킷을 얻을 수도 있습니다.

    나는 비동기 UDP를 사용했는데, io_service.run()을 호출하면 무기한 차단되므로 실제로 도움이되지 않습니다.

    나는 블로킹 소켓 읽기를 시간 초과하는 것으로 생각했지만, 부스트 호출을해야만 할 것 같아 보이지 않는다.

    대답은 스레딩과 관련이 있습니까? 어느 쪽이든, 누군가가 친절하게 다소 비슷한 예를 지적 할 수 있습니까? 확실히 이것은 이전에 행해졌 다.

  • +0

    +1 멋진 첫 번째 질문, SO에 오신 것을 환영합니다 –

    +0

    긴 시간 lurker, 처음으로 포스터. 나는 reddit 다음에 할 것이다 :) – Grommit

    답변

    3

    io_service::run()에서 차단을 방지하려면 io_service::poll_one()을 사용할 수 있습니다.

    UDP 패킷을 잃어 버리는 것에 대해서는 운이 없다고 생각합니다. UDP는 배달을 보장하지 않으며 많은 트래픽이있는 경우 네트워크의 모든 부분에서 UDP 패킷을 삭제할 수 있습니다. 전달을 확실하게해야한다면, 일종의 흐름 제어를 구현하거나 TCP 만 사용해야 할 필요가 있습니다.

    +1

    고마워. 나는 패킷을 떨어 뜨리는 네트워크에 대해 너무 걱정하지 않는다. 나는 단지 5 %의 시간만을 찾고있는 인스턴스를 갖고 싶지 않으므로 디자인 상으로는 패킷의 95 %를 놓친다. 그들이 나중에 컬렉션을 기다리는 동안 잠시 바쁘다면 나는 괜찮습니다. – Grommit

    +0

    비동기 읽기를 사용하면 운영 체제가 패킷을 수신하고'run','run_one','poll' 또는'poll_one' 중 하나를 호출 할 때 전달할 수 있습니다. – TAS

    +0

    @ Grommit poll_one과 같은 것을 사용할 때 조심해야 할 것은 서버에 대기열이 너무 많아지고 서버에 뒤쳐져 있다는 것입니다 (특히 주 루프가 잠시 동안 일시 중지되어야하는 경우). –

    3

    당신의 문제는 당신이 여전히 동 기적으로 생각하고 있다고 생각합니다. 비동기로 생각해야합니다.

    1. UDP 소켓에서 비동기 읽기 - 데이터가 도착하면 처리기를 호출합니다.
    2. 들어오는 데이터를 처리합니다. 처리하는 동안 하나의 스레드 만 있으면 아무 것도 발송하지 않습니다. 이것은 완벽하게 OK 일 수 있습니다 (UDP 메시지는 여전히 네트워크 스택에 대기합니다 ...).
    3. 이렇게하면 다른 비동기 작업을 시작할 수 있습니다.

    스레드와 관련된 본질적으로 관련이 없거나 오프라인 인 작업을 병렬로 수행해야하는 경우. io_service.run()을 호출하는 스레드를 만듭니다.

    asynch 프레임 워크에서 주기적으로 작업해야하는 경우 timers을 사용하십시오.특정 예에서

    우리가 이런 일을 다시 정렬 할 수 있습니다 (사이비 코드) :

    read_handler(...) 
    { 
        modify_a_with_data_from_b(a,b); 
        do_stuff2(a); 
        a = do_stuff1(); 
        udp->async_read(..., read_handler); 
    } 
    
    periodic_handler(...) 
    { 
        // do periodic stuff 
        timer.async_wait(..., periodic_handler); 
    } 
    
    main() 
    { 
        ... 
        a = do_stuff1(); 
        udp->async_read(..., read_handler) 
        timer.async_wait(..., periodic_handler); 
    
        io_service.run(); 
    } 
    

    은 지금 당신의 질문에서 명확하지 않은 다른 요구 사항이 확실하지만거야 그들에게 비동기적인 대답을 알아 내야 할 필요가 있습니다. 이것은 단지 하나의 아이디어 일뿐입니다. 또한 비동기 프레임 워크가 필요하거나 동기 소켓 API 만 사용해야하는지 스스로에게 물어보십시오.

    +0

    그는 60hz에서 뛰려고하기 때문에 타이머 해상도를 조심해야합니다 ... asio는이 문제를 해결할 수있는 high_resolution_timer typedef를 제공합니다 (직접 사용하지는 않은 것 같습니다). –

    +0

    @NathanMonteleone : 예. 나는 대부분의 플랫폼에서 데드 라인 타이머가 1ms 해상도를 제공 할 것이라고 생각하지만 이는 검증 될 필요가있다. 지터가 있으면 OK이지만 쉽게 수행 할 수있는 오류를 축적하고 싶지는 않습니다. 실시간 요구 사항이 더욱 까다로워지면 조금 더 복잡해집니다. –