UDP 비 차단 또는 수신을위한 별도의 스레드?


10

멀티 플레이어 게임을 만들고 있습니다 (64 명 미만). 이미 네트워크 루프에 별도의 스레드를 사용하기로 결정했지만 UDP 수신을 위해 추가 스레드를 생성하거나 비 차단 (수신 스레드없이) 수신 소켓을 설정하는 것이 더 좋은지 궁금했습니다.

아니면 비동기 소켓과 같은 다른 방법을 사용하는 것이 더 낫습니까? 더 나은 방법은 언제나 환영합니다!

답변:


6

우선, 무언가가 있고 작동하는 경우 일반적으로 그대로 두는 것이 좋습니다. 왜 깨지지 않은 것을 고쳐야합니까?

그러나 문제가 발생하여 네트워킹 코드를 다시 작성하려면 네 가지 주요 선택이 있다고 생각합니다.

  1. 다중 스레드 차단 코드 (현재하고있는 작업)
  2. 레벨 트리거 알림이있는 비 차단 소켓
  3. 준비 변경 알림이있는 비 차단 소켓
  4. 비동기 소켓

피어-투-피어에서 대규모 멀티 플레이어에 이르는 많은 멀티 플레이어 클라이언트와 서버를 작성 했으므로, 옵션 2는 서버와 게임의 클라이언트 부분 모두에 대해 최소한의 성능으로 매우 복잡하지 않다고 생각합니다. 마지막으로 옵션 4를 사용하지만 일반적으로 전체 프로그램을 다시 생각해야하며 클라이언트가 아닌 서버에 유용합니다.

특히 멀티 스레드 환경에서 소켓을 차단하지 않도록 권고하고 싶습니다. 일반적으로 잠금 및 기타 동기화 기능으로 이어지며 코드의 복잡성을 크게 증가시킬뿐만 아니라 일부 스레드가 대기 할 때 성능이 저하 될 수 있습니다 다른 사람.

그러나 무엇보다도 대부분의 소켓 구현 (및 대부분의 I / O 구현)은 가장 낮은 수준에서 차단되지 않습니다. 사소한 프로그램의 개발을 단순화하기 위해 단순히 차단 작업이 제공됩니다. 소켓이 차단되면 해당 스레드의 CPU가 완전히 유휴 상태이므로 이미 차단되지 않은 작업에 대한 차단 추상화에 대해 차단되지 않은 추상화를 작성하는 이유는 무엇입니까?

비 블로킹 소켓 프로그래밍은 시도하지 않으면 약간 어려워 보이지만 매우 간단하며 이미 입력 폴링을 수행하는 경우 비 블로킹 소켓을 할 마음가짐이 있습니다.

가장 먼저 할 일은 소켓을 비 블로킹으로 설정하는 것입니다. 당신은 그걸로fcntl() .

그 후, 당신이하기 전에 send(), recv(), sendto(), recvfrom(), accept()( connect()당신은 호출 스레드를 차단할 수 또는 다른 통화 비트 다른입니다) select()소켓에.select()소켓을 차단하지 않고 후속 읽기 또는 쓰기 작업을 수행 할 수 있는지 여부를 알려줍니다. 이 경우 원하는 작업을 안전하게 수행 할 수 있으며 소켓이 차단되지 않습니다.

이것을 게임에 포함시키는 것은 매우 간단합니다. 예를 들어 다음과 같이 게임 루프가 이미있는 경우 :

while game_is_running do
    poll_input()
    update_world()
    do_sounds()
    draw_world()
end

다음과 같이 변경할 수 있습니다.

while game_is_running do
    poll_input()
    read_network()
    update_world()
    do_sounds()
    write_network()
    draw_world()
end

어디

function read_network()
    while select(socket, READ) do
        game.net_input.enqueue(recv(socket))
    end
end

function write_network()
    while not game.net_output.empty and select(socket, WRITE) do
        send(socket, game.net_output.dequeue())
    end
end

리소스 측면에서, 내가 가지고있는 유일한 책이라 할지라도 모든 사람들이 자신의 책장에 있어야한다고 생각하는 유일한 책은 " Unix Network Programming, Vol 1입니다. Richard Stevens의 "입니다. Windows 또는 다른 OS 또는 언어 소켓 프로그래밍을 수행하는 것은 중요하지 않습니다. 이 책을 읽을 때까지 소켓을 이해한다고 생각하지 마십시오.

다중 소켓 프로그래밍 (주로 서버 프로그래밍과 관련) 측면에서 사용 가능한 솔루션에 대한 일반적인 개요를 찾을 수있는 다른 리소스는 이 페이지 입니다.


방금 게임 엔진을 시작했기 때문에 재 작성은 문제가되지 않습니다. 이 답변은 정말 유용했으며 도서 추천에 감사드립니다. 게임에서 네트워킹에 대해 더 구체적인 책을 알고 있습니까?
Yannick Lange

3
@YannickLange : 아니요.하지만 네트워킹은 장르에 구애받지 않고 게임에 관련된 책을 찾지 않는 것이 좋습니다. 또한 다른 책은 Stevens의 책 수준만큼 올라가지 않습니다. 메시지 지향 프로토콜을 사용하는 것이 메시지 지향 프로그램 (대부분의 게임과 같은)을 작성할 때 UDP를 사용하는 것이 좋습니다. 많은 사람들이 TCP를 통해 메시지 추상화를 작성하는 경향이 있는데, 이는 자체적으로 메시지 지향 프로토콜 (IP)을 통해 구축 된 스트림 지향 추상화입니다.
Panda Pajama

-1

사용중인 프로그래밍 언어를 쓰지 않았지만 대부분의 언어는 종종 기본 운영 체제의 기능을 활용하는 우수한 비동기 소켓 프레임 워크를 제공합니다.

블로킹 소켓을 기반으로 자체 스레드 구현을 작성할 때 (여러 개의 클라이언트가있는 경우 모든 단일 소켓에 대한 스레드가 필요함) 비동기 소켓 프레임 워크가 이미 제공하는 것을 다시 발명하려고합니다.

따라서 비동기 소켓을 사용하는 것이 좋습니다.


4
왜 모든 단일 소켓에 스레드가 필요합니까? 특히 비동기 소켓? 많은 헤비급 서버는 "스레드 풀"모델을 사용하여 소켓 데이터를 처리합니다. 여기서 각 스레드는 N 개의 클라이언트에 서비스를 제공하고 필요에 따라 생성 또는 종료됩니다. 이 답변에 개선이 필요하다고 생각하십시오 : D
그림 쇼

@ 그림 쇼 내 대답을 오해했다고 생각합니다. 블로킹 소켓을 사용할 때 멀티 스레드 모델이 필요하다는 것을 분명히 알았습니다.
Philipp

@ 필립 (Philipp) 나는 어떤 프로그래밍 언어를 사용하는지 말하지 않았다. 왜냐하면 그것이 질문과 관련이 없다고 생각했기 때문이다. 비동기 소켓을 사용하는 것이 좋습니다. 게임 (엔진)에서 이러한 유형의 방법을 배우기위한 권장 도서 / 웹 페이지를 알고 있습니까?
Yannick Lange

@ 그림 쇼 : 그리고 각 스레드는 어떻게 N클라이언트를 서비스 합니까? 차단하고 있고 나머지 소켓의 상태에 관계없이 각 소켓이 데이터를 처리하도록하려면 소켓 당 하나의 스레드가 있어야합니다. 차단 소켓을 사용하지 마십시오.
Panda Pajama

내 의견은, 당신의 대답의 첫 번째 버전에 있던 반면에, 당신이 그것을 편집하고 수정, 잊지 내가 말한 : D
그림 셔
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.