2012-11-09 3 views
4

recvfrom을 통해 패킷의 일부를 받으려고합니다. 실제로 다음과 같이 작동recvfrom (UDP)을 통해 패킷의 일부를 수신합니다.

recvfrom(sockfd, serialised_meta, 12, flags, src_addr, addrlen); 
recvfrom(sockfd, serialised_buf, BUFLEN, flags, src_addr, addrlen); 

데이터는 다음과 같이 전송됩니다

bufd->Serialise(serialised_buf, BUFLEN+12); 
sendto(sockfd, serialised_buf, BUFLEN+12, flags, dest_addr, addrlen); 

그래서 아이디어는 먼저 몇 가지 메타 데이터를 읽고 다음 다른 뭔가를받을 것인지 여부를 결정하는 것입니다. 문제는 두 번째 버퍼 (serialised_buf)가 처음에 4 '/ 0'바이트를 수신한다는 것입니다. 직렬화 문제가 아닌 것 같아요. 전에 직렬화를 사용했고, 모든 패킷 (메타 및 데이터)을 즉시 수신하는 동안 모든 것이 멋졌습니다. 수정 방법에 대한 아이디어가 있으십니까?

추신. 나는 불필요한 바이트를 건너 뛸 수 있음을 이해한다.)하지만 어쨌든, 왜 그런 일이 일어 났을 까?

답변

10

UDP는 "스트림"프로토콜이 아닙니다 ... 초기 recvfrom을 수행하면 패킷의 나머지 부분이 삭제됩니다. 두 번째 recvfrom은 다음 패킷을 기다리고 있습니다 ...

+0

그렇다면 내 솔루션이 어떻게 작동할까요? 그것은 호기심에서 벗어난 것입니다.) 패킷의 나머지 부분이 버려지면 두 번째 recvfrom 작동해야합니다. 미리 감사드립니다. 그리고 지금, 메타를 먼저 얻는 가장 좋은 방법은 픽 플래그를 사용하는 것입니다. – Roman

+0

패킷 길이에 대해서 이야기하고 있다면,'FIONREAD'와 함께'ioctl'을 사용하여 패킷 길이를 결정할 수 있습니다. 'MSG_PEEK'을 사용할 수는 있지만 패킷 데이터가 크고 메타가 작지 않으면 귀찮게하지 않을 것입니다 ... 아마도'ioctl'을 건너 뛰고 최대 버퍼 크기를 갖는 것이 가장 좋습니다 (애플리케이션에 대해) 가서 데이터를 건너 뛰거나 버리십시오. – mark

3

UDP는 TCP와 같은 스트림이 아니라 메시지에 대해 작동합니다. UDP를 사용할 때 sendto()recvfrom() 사이에는 일대일 관계가 있습니다. UDP에서 부분 데이터를 수신 할 수있는 옵션이 없으며, 전부 또는 일부 유형의 전송입니다. 당신은 recvfrom() 전체 BUFLEN+12 메시지를 한 번에 가지고 있어야하고, 실제로 사용할지 여부를 결정해야합니다. 그것은 UDP가 작동하는 방식입니다.

+0

정말 다 끝났어? 나는'recvfrom()'의 반환 값을 항상 확인하고 예상 된 크기와 비교 한 다음 모든 데이터가 수신 될 때까지 반복적으로'recvfrom'를 호출해야한다는 것을 기억합니다. 불행하게도 나는 그것을 어디에서 읽었는지 기억하지 못한다. 이것이 의미가 없다면, 내 인생을 좀 더 편하게 해줄 것입니다.) – user463035818

+0

... 내가 설명한 것은 TCP에만 필요하지만 UDP에는 필요하지 않을 수도 있습니다. 나는 그들이 TCP를 위해 그 라인을 따라 무언가를 묘사하는 사이트를 발견했다. (내가 언급하고있는 것은 아니지만 다소 차이는 있지만 똑같은 기술이다. http://www.binarytides.com/receive-full-data-with-recv -socket-function-in-c /) – user463035818

+1

@ tobi303 이는 UDP가 아닌 TCP에서 일어나는 일입니다. 리턴 값은 참으로 읽은 바이트 수이지만 제공된 버퍼가 전체 메시지를 수신하기에는 너무 작 으면 UDP의'recvfrom'은 가능한 한 버퍼를 채우고 나머지 읽지 않은 데이터는 버리고'EMSGSIZE '오류. 따라서 전체 메시지를 수신 할 수있는 기회는 한 번뿐입니다. –

관련 문제