• 카테고리

    질문 & 답변
  • 세부 분야

    시스템

  • 해결 여부

    미해결

partial send/recv에 관하여

20.06.09 11:04 작성 조회수 484

1

어떤 상황에서 partial send 또는 recv 가 발생하는지 그리고 수업에서 partial send, recv를 처리하는 방법에 대한 문의입니다.

partial send :

- 내 시스템의 send sock buffer가 꽉 찬 경우...

- send sock 이 nonblock 옵션인 경우...

맞는지요???

반면에 partial recv 같은 경우는 어떤지요. 

그리고 상대방이 몇 바이트의 패킷을 보낼지 모르는 경우에는

보통 아래 len를 어떻게 설정하나요?

되도록 패킷이 짤리지 않고 받게 하려면 버퍼를 크게 잡고

len를 최대한 크게 하는게 맞는 것인지

그리고 partial recv와는 반대로 2, 3개의 패킷이 한번에

수신되는 경우도 있습니다. 그럼 결국 수신버퍼를

circular Queue 처럼 구현해야 하는 건가요???

상대방이 어떻게 보내더라도 수신 데이터 파싱할때

데이터 유실없이 구현하는게 목적입니다.

보통 수신 버퍼 관리를 어떻게 하는지 모범(?)사례를 보고 

싶습니다.  강사님. 감사합니다. 

recv( SockFd, ( char * )&RcvBuf, len, 0 );

답변 1

답변을 작성해보세요.

0

partial send/recv가 발생하는 원인은 여러 가지 입니다. 말씀하신 대로 buffer가 부족한 경우도 발생할 수 있을 것이고, (네트워크 통신의 경우에는)물리적으로 패킷이 늦게 도착하는 경우도 있을 수 있겠죠. 여러 가지 원인이 있을 수 있기 때문에 소켓 프로그래밍을 하는 관점에서는 partial send/recv가 발생하는 원인보다는 발생했을 때 대응을 어떻게 하느냐가 중요한 점이라고 할 수 있겠습니다.

소켓 통신에서 데이터는 byte-stream 입니다. 시작과 끝을 알기 힘들죠. 그래서 네트워크 프로토콜에서는 크게 두 가지 방법을 사용해 패킷의 시작과 끝(즉, 데이터의 시작과 끝)을 인지합니다. 첫 번째 방법은 데이터 전송의 단위를 고정길이로 하는 것입니다. 예전 ATM 망에서 사용하던 방식 입니다. 이 방식을 사용하는 프로토콜이 많지는 않은 것 같습니다. 프로토콜 기능의 확장성 측면에서 좋지 않아서 그런 것 같습니다. 두 번째 방법은 고정길이의 헤더 + 가변길이의 데이터로 구성하는 것입니다. 헤더 안에는 뒤따라올 가변길이 데이터의 길이가 명시되어 있어 데이터의 시작과 끝을 정확히 인지하게 됩니다. Ethernet과 IP, TCP, UDP 등 대부분의 프로토콜이 이와 같은 방식을 사용합니다.

고정길이 방식의 수신 데이터 처리는 간단합니다. 무조건 정해진 길이까지 받아져야 온전한 데이터로 판단하고 데이터를 처리할 수 있습니다. partial recv가 된 경우에는 남은 길이만큼만 수신하도록 해서 온전한 데이터를 받을 수 있습니다.

가변길이 방식의 수신 데이터 처리는 먼저 헤더를 온전히 받아야 합니다. 헤더를 받을 때 partial recv가 되었다면, 고정길이 방식의 수신 데이터 처리처럼 남은 길이만큼만 수신하도록 해서 헤더를 온전히 받습니다. 그 후에 헤더에 적혀있는 가변길이 데이터 만큼 데이터를 수신합니다. 데이터의 길이가 정해져있기 때문에 partial recv가 발생하더라도 온전히 처리할 수 있습니다. 

경우에 따라 다르겠지만, 패킷 데이터 처리 시 circular queue는 잘 사용하지 않습니다. 데이터의 길이와 관계없이 데이터를 최대한 많이 받은 다음, 그 안의 데이터를 하나씩 처리해가는 방식을 생각하신 것 같습니다. 이런 방식이면 가장 뒤쪽에 잘리는 데이터 처리가 난해하게 되죠. 이런 방식 보다는 받을 데이터 만큼씩만 받는 방법이 더 유용합니다. pseudo code로 표현하자면 다음과 같습니다.

start_of_loop:
  receive(&hdr, sizeof(hdr));               //단, receive()는 partial recv를 처리할 수 있음
  receive(&buffer, hdr.size);
  processing_data(hdr, buffer);
end_of_loop

장문의 답변글이 되었네요. 도움이 되셨길 바랍니다. 좋은 질문 감사합니다. :)