오프라인 게임과 온라인의 차이 |
요즘 게임은 보통 60fps로 동작합니다.
1초에 60번 그림을 그리므로 1프레임당 처리 시간은 다음과 같습니다.
1,000(ms)/60(frame) = 16.666...(ms/frame)
즉 16ms안에만 통신이 보장된다면 상관없겠지만....
때때로 100ms전후의 지연이 발생할 때가 있습니다.
통시이 만약 100(ms)지나서 온다면..
대략 7프레임이 지나서 도착한다는 이야기입니다.
따라서 온라인 게임과 같이 통신을 필요로 하는 게임을 제작할시에는 반드시 정보를 송신한 쪽과 수신한 쪽의 같은 프레임에서 처리되지 않는다는 사실을 전제로 제작해야 합니다.
이와같이 소프트웨어로는 도저히 극복하기 힘든 한계가 있기 때문에 오프라인과 온라인은 별개의 게임입니다.
통신방식 |
▷ 동기 방식
통신할 단말 사이엥서 데이터르 주고받아 각 단말의 처리 결과가 완전히 일치하는 통신방식.
턴 동기 : 턴 방식 게임에서 턴 플레이어의 행동을 상대에게 보내고 그 정보를 바탕으로 처리합니다.
키 입력 동기 : 컨트롤러의 입력 정보를 서로 전송하여, 같은 프레임의 데이터를 처리함으로써 단말을 같은 상태로 동시킬 수 있는 동기 방식입니다.
▷ 비동기 방식
꼭 필요한 정보만으로 각 단말의 상태를 일치시키는 방식입니다. 동기방식과 달리 단말간의 처리가 완전히 일치하지는 않습니다.
따라서 자신의 단말과 상대방 단말과의 일관성을 잃어버립니다. 그러므로 통신프로그램은 오류 발생이 당연하다는 것을 전재로 만들어야 합니다.
게임 제작시 고려해야할 사항 |
▷ 통신 지연
플레이어가 지연을 느낄 수없는 게임 디자인이 필요합니다.
▷ 데이터 소실
데이터가 소실 되었을 때 대처할 방법을 생각합니다.
데이터 소실 시 데이터를 재송신할지, 재송신될 때까지 게임은 어떻게 처리할지 등등
▷ 회선이 끊길 때
남은 플레이어로 게임을 게속할 것인지..
끊긴 플레이어를 대기할 것인지..
게임은 끝낼 것인지..
제작 개념 |
1 : 1 격투 게임을 제작한다면 등장하는 캐릭터는 몇 명일까요..?
2명이라 생각하겠지만 4명입니다.
1Player 단말기 : 1P 조정캐릭터, 2P 통신대기 캐릭터
2Player 단말기 : 2P 조정캐릭터, 1P 통신대기 캐릭터
이런 이유로 딜레이가 발생하면 오류가 뿜뿜 터질겁니다. 이런 오류를 어느정도 굴러가면 되겠지 하고 적당히 처리하고 넘어가면 프로젝트를 완성 후에 에러가 터지면 에러를 확인하는 것에 몇십배의 시간이 요구됩니다.
처음에 잘 돌아가다가 하나의 틀어짐 때문에 심각한 버그가 발생한다면 그 게임은 접거나 밤새서 찾아내거나 둘중에 하나겠죠.
이를 방지하기 위해서 통신프로그래밍에서는 에러처리를 완벽하게 해도 부족합니다.
물론 다른 프로그램도 이렇게 하면 좋지만요..
용어 정리 |
단말 : 네트워크에 연결된 컴퓨터, 게임기, 휴대전화, 태블릿 등등
플레이어: 단말로 게임을 플레이하는 유저
캐릭터 : 플레이어가 겡미 세계에서 조정하는 주인공
로컬 단말 : 자신이 플레이하는 단말
리모트 단말 : 통신 상대의 단말
로컬 캐릭터: 로컬 단말에서 조종하는 자신의 캐릭터
리모트 캐릭터 : 리모트 단말에서 통신 상대방이 조종하는 로컬 단말 캐릭터
게임 서버 : 게임 플레이 중에 단말과 저속해서 게임 데이터를 일원적으로 관리하거나 호스트와 게스트의 데이터를 중계하는 서버
게임 클라이언트 : 게임 서버와 통신해서 게임을 플레이하는 단말
호스트 : 통신 회선으로 접속된 온라인 게임 단말 중 게임을 진행하고 데이터를 관리하는 단말
게스트 : 통신 회선으로 접속된 온라인 게임 단말 중 게임 진행 정보를 호스트에서 받아서 게임을 진행하는 담라
게임 어플리케이션 : 게임을 움직이는 프로그램
게임 처리 : 게임 애플리케이션에서 게임 부분만 처리한다. 통신이나 그래픽 등의 시스템 처리를 제외한 게임을 플레이하기 위한 처리를 가리킨다.
데이터는 어떻게 전달될까 |
데이터는 패킷이라는 그릇에 담겨서 운반됩니다.
단순하게 아래의 순서가 통신의 정보입니다.
단말기 -> 통신장치 -> 통신상대의 단말
한 사람과 통신을 하지는 않을 겁니다.
단말0 -> 통신장치 -> 통신상대의 단말1
통신상대의 단말2
이렇게되면 누구에게 보내야 될지 구분이 안가서 이름을 붙여줍니다.
이를 IP주소라고 합니다.
단말기 -> 통신장치 -> 통신상대의 단말1 (IP : 192.168.1.1)
통신상대의 단말2 (IP : 192.168.1.2)
이렇게 구분을 해두었으니 단말이 두명이되면 단말1씨에게는 데이터1을 단말2씨에게는 데이터2를 줄 수도 있겠죠.
단말기 -> 통신장치 -> 통신상대의 단말1 (IP : 192.168.1.1)
통신상대의 단말2 (IP : 192.168.1.2) (데이터2수신)
여기서 문제점이 있습니다. 단말2 씨에게 데이터를 전달했는데 단말씨의 컴퓨터에 프로그램이 너무 많이 켜져있습니다.
한굴, 뽀로샵, 게임프로그램, 야구동영상!? 이렇게 많은 프로그램이 켜져 있을대 어느 프로그램이 받아야되는지 혼돈이 생기네요.
그래서 프로그램에 이름을 붙여줍니다. 이를 포트(port)라고 합니다.
단말기 -> 통신장치 -> 통신상대의 단말1 (IP : 192.168.1.1 : 5000)
통신상대의 단말2 (IP : 192.168.1.2 : 5001)
또.. 문제가 터졌습니다.
운반중에 데이터가 사라졌습니다. ㅠㅠ
이 문제는 어떻게 대처를 해야할가요? 데이터를 분실했을때 어떻게 처리하는지 규칙을 정하는 것이 좋겠죠?
이를 위해서 프로토콜이라는 통신약속이 나타납니다.
TCP |
믿을 수 있는 TCP약속은 확실하게 데이터를 전달할 수 있는 체계입니다.
단말0 : TCP씨 데이터 배달 부탁엽
TCP씨 : 단말1씨 배달해도 될갑쇼? 살아계신가요?
단말1씨 : ㅇㅇ 살아있어요 보내주세요
TCP씨 : (운반함) 배달왔습니다.
단말1씨 : ㅇㅇ 감사
TCP씨 : 단말0씨 배달 완료했어요
실제 통신은 위와 같습니다.
1. TCP의 접속처리를 이용합니다.
2. 받는곳에 확인응답(ACK : Acknowledgement)요청을 합니다.
3. 확인응답(ACK : Acknowledgement) 답장이 돌아옵니다. 이렇게 되면 접속완료 입니다.
4. 데이터를 보낼 수 있는 상태라면 TCP 데이터를 전송합니다.
5. 데이터를 수신해서 이상없으면 수신완료 메시지를 보냅니다.
6. 보낸 곳에서 확인응답 메시지를 받으면 통신이 끝납니다.
만약 일정시간 동안 확인응답이 돌아오지 않으면 다시 같은 데이터를 송신합니다.
▷ 큰 데이터 처리하기
데이터의 전송과 순서를 보증하므로 HTTP와 FTP에서 사용되는 프로토콜 입니다.
전송할 데이터가 크면 TCP는 데이터를 세그먼트라는 데이터로 작게 나누고 TCP가 다룰 수 있는 헤더를 세그먼트에 붙입니다.
TCP는 애플리케이션에서 보낸 스트림데이터를 버퍼에 저장하고 데이터를 세그먼트로 나누어 송수신 합니다.
수신한 쪽은 세그먼트를 다시 결합해서 애플리케이션에 전달합니다.
▷ 장점
전달을 보증한다.
순서를 보증한다.
혼잡을 제어한다.
▷ 단점
처리가 복잡하므로 전송 속도가 느리다.
UDP |
사례1)
단말0 : UDP씨 데이터 배달 부탁엽
UDP씨 : TCP씨 : (운반함) 배달왔습니다. 없네? 그럼 데이터는 버려야지.
사례2)
단말0 : UDP씨 데이터 배달 부탁엽
UDP씨 : TCP씨 : (운반함) 배달왔습니다. 있네? 받으슈
▷ 장점
처리가 단순하고 전송 속도가 빠르다.
▷ 단점
전달을 보증하지 않는다.
순서를 보증하지 않는다.
RUDP |
표준 프로토콜이 아닙니다. SDK로 별도로 제공되거나 프로토콜 사양에 맞게 직접 구현해야 사용할 수 있습니다.
재전송 기능을 구현한 UDP를 이용할 수 있으면 송신할 패킷을 TCP처럼 다룰 수 있습니다.
지연시간 |
▷ 편도 지연시간(레이턴시)
A단말에서 데이터를 송신한 시각과 B단말에 전달된 시각 사이에서 지연된 시간차이
▷ 왕복 지연시간(레이턴시)
A단말에서 데이터를 송신한-> B단말에 데이터 받음 -> B가 A단말에 확인응답을 전달 -> A단말이 확인 응답을 수신
위의 과정을 왕복 지연시간이라고 하며 RTT(Round Trip Time)라고도 함.
통신량 |
통신은 물이 흐르는것을 생각하면 이해하기가 쉽습니다.
물이 흐르는 관이 넓으면(통신대역) 많은 양이 운반될 것입니다.
송신하기 전까지 여러개의 라우터와 허브를 지나게 됩니다.
접속 경로와 회선 상황에 따라서도 흐르는 양이 달라집니다.
1초에 몇 비트 전송되는지 나타내는 bps(bit per second)로 측정할 수 있습니다.
통신에는 통신 경로에 있는 기기와 회선 품질에 따른 제약이 있으므로 항상 통신 대역을 신경 쓰면서 데이터를 송수신 해야 합니다.
소켓 |
TCP와 UDP를 간단하게 다루기위한 통신API입니다. IP주소와 포트번호를 한 조로 통신상대를 지정하고 통신합니다.
서버 | 클라 | |
전화받을 준비 | 대기 | |
소켓 준비 | <--> | 소캣 생성 |
주소 발급 | <--> | 포트 번호 할당 |
소켓 활성화 | <--> | 대기 시작 |
그럼 실제 프로그램에서 과정은..
소켓생성 -> bind -> Listen -> Accept -> 통신 -> 통신종료
연결될때 하나의 서버가 사용하는 소켓에서 통신하는 것이 아니라
또 다른 소켓을 생성하여 그 소켓을 관리하면서 통신한다.
열려있는 ip 와 Port보기 |
팁 : 열려 있는 포트보기 cmd -> netstat -ano
0.0.0.0 으로 시작하는건 자기 IP이고
127.0.0.1은 자기 자신을 뜻한다.
192.0.0.?? 같은 경우는 대부분 현재 공유기 아이피이다.
대부분 ipconfig누르면 공유기 ip가 뜨는데
자신의 ip(라우터)를 찾고 싶다면 네이버에 내 아이피를 입력하면 나온다.
그리고 네이버에서 찾은 아이피로 접속을 한다면 연결이 안된다.
자신의 라우터까지만 라우터에서 다시 뿌려줘야하는데 어디에 뿌려줘야 하는지 모르는 상태이기 때문!
따라서 포트포워딩을 해야한다.
따라서 기본 게이트웨이(라우터 주소)를 입력해서 라우터 관리프로그램에 접속한뒤 포트포워드를 설정하면 잘 접속된다.
모바일을 서버로 만들고 싶다면
모바일 아이피타임 포트포워딩 구글링해서 접속시키면 된다.
이렇게해도 안된다 싶으면 방화벽들어가서 Port 예외처리해주자.
접속 오류시.. |
참조 : 링크
체크 해보기)
ex) netstat -na
ex) tracert 22.110.0.1
ex) arp -a
에러메시지 |
no route to host
ENETUNREACH OR EHOSTUNREACAH - 클라이언트가 보낸 패킷이 서버 네트워크까지는 잘 전달 되었다. 그런데 그 네트워크에 있는 디폴트 게이트웨이가 호스트 주소에 해당하는 호스트를 찾기 위해서 ARP메시지를 브로드캐스팅하게 되는데, 아무도 ARP메시지에 응답을 하지 않게 되면 그 디폴트 게이트웨이(라우터)는 클라이언트가 보낸 패킷을 받을만한 서버 호스트가 없다고 판단해서 ICMP메시지를 클라이언트에게 되돌려준다. 그렇게 되면 클라이언트는 라는 메시지no route to host를 출력하게 된다.
1. 할당받은 기계가 없는경우.
2. arp주소에 mac주소가 등록되지 않은 경우..
해결책)
(링크) 액세스 포인트를 변경했고 앱이 작동했습니다. 앱은 로컬 IP를 사용하여 서버에 액세스
세팅 -> 모바일 네트워크 -> 엑세스 포인트 -> 추가 및 변경
참조