• 카테고리

    질문 & 답변
  • 세부 분야

    게임 프로그래밍

  • 해결 여부

    미해결

패킷조립순서

21.09.18 22:08 작성 조회수 226

0

강의도 보고 다른분들 질문도 보고 있습니다.
void RegisterRecv()
{
    _recvBuffer.Clean();
    ArraySegment<byte> segment = _recvBuffer.WriteSegment;
    _recvArgs.SetBuffer(segment.Array, segment.Offset, segment.Count);

    ...
}

불완전한 패킷은 조립가능할때까지 기다렸다가 조립해서 해석하는 것까지는 알겠는데, 어디서 모아놓는지 헷갈려서 복습을 하면서 찾아보았습니다.

위의 RegisterRecv메소드의 _recvArgs.SetBuffer에서 Recv데이터를 모아놓는게 맞나요?

①여기서 처리가능하면 처리후 _recvBuffer.Clean()을 통해 위치를 처음으로 돌려주고 ②처리가 불가능하다면 계속 기다리다가 다음 패킷이 오면 현재의 _readPos, _writePos 기준으로 다음 데이터를 받아서 처리- 맞게 이해했을까요?



그리고 만약에

지금 RecvBuffer의 크기가 1024인데 800짜리 패킷이 400만 도착해서 대기중입니다.

그때 다음 패킷이 잘린 400+새 패킷 800 해서 1200이 들어와 버리면 => 400짜리 패킷(a-1)+400짜리 패킷(a-2)+800짜리 새 패킷(b)이렇게 될텐데,

1024를 넘어 버리게 들어오면 어떻게 되나요? 애초에 이렇게 들어올 수 있을지는 모르겠지만;;(잘린 패킷이 다음패킷에 붙어서 올수가 없나요?)

답변 1

답변을 작성해보세요.

1

①여기서 처리가능하면 처리후 _recvBuffer.Clean()을 통해 위치를 처음으로 돌려주고 ②처리가 불가능하다면 계속 기다리다가 다음 패킷이 오면 현재의 _readPos, _writePos 기준으로 다음 데이터를 받아서 처리- 맞게 이해했을까요?

네 맞습니다!

위 부분입니다.


강의 코드 기준으로 OnRecv 함수가 얼마나 처리했는지를 int로 반환하는데,
그만큼을 딱 컨텐츠 코드에서 처리한 것이라 볼 수 있습니다.
로컬 테스트에선 대부분 딱 보낸만큼을 바로 처리하고
패킷이 분할되어 오는 경우도 거의 없겠지만,
서버에 아주 많은 부하가 걸리고 사람들이 한군데에 모여 있으면
심심찮게 분할되어 오는 패킷이 발생하게 됩니다.

그때 다음 패킷이 잘린 400+새 패킷 800 해서 1200이 들어와 버리면 => 400짜리 패킷(a-1)+400짜리 패킷(a-2)+800짜리 새 패킷(b)이렇게 될텐데,
1024를 넘어 버리게 들어오면 어떻게 되나요? 애초에 이렇게 들어올 수 있을지는 모르겠지만;;(잘린 패킷이 다음패킷에 붙어서 올수가 없나요?)

우리가 유저레벨에서 데이터를 냠냠 뽑아먹기 위해 사용하는 버퍼와
실제로 커널 버퍼에 내용물을 저장하는 버퍼는 별개로 있습니다.
따라서 [400] + [400 + 800] 이렇게 들어오더라도 문제 없습니다.
위 가정에서 유저레벨 버퍼가 1024 한도라면 [400]+[400 + 224] 가 일단
커널레벨->유저레벨로 복사되구요.
그러면 앞단의 완성된 800을 먼저 처리해주고 224의 찌꺼기가 남게 됩니다.
요 찌꺼기는 다음 턴에 나머지 데이터가 오면 마찬가지로 소모될 예정이니 신경쓸 필요 없습니다.

루라님의 프로필

루라

질문자

2021.09.21

답변감사합니다!

커널레벨에 먼저 쌓이고 유저레벨에서 설정한 만큼 꺼내서 처리하는거군요.

그럼 커널레벨의 크기는 얼마인지도 알 수 있나요? 받기만하고 꺼내쓰지않는다면 어떻게 되나요?

커널 송수신 버퍼의 크기도 설정하는 함수가 있습니다.
그리고 받기만 하고 꺼내쓰지 않으면, 커널 버퍼가 꽉 차서
상대방이 더 이상 데이터를 보낼 수 없게 됩니다.
TCP 프로토콜 차원에서 상대방의 버퍼 여유 상황을 보고 보내기 때문이죠.
이 부분은 나중에 TCP/IP 이론에 대해 공부하면 알 수 있습니다.