2009-06-09 3 views
1

비동기 소켓을 사용하여 가변 길이 메시지를 전송하는 방법에 대해 an article on Vadym Stetsiak's blog을 읽었습니다.비동기 요청한 모든 바이트를 읽지 않고 수신 할 수 있습니까?

그는 말한다 : 서버에 도착하면 여러 메시지

무엇을 기대? 여러 메시지를 처리하는 동안 수신 작업은 그물에서 읽히는 임의의 바이트 수를 반환 할 수 있음을 기억해야합니다. 일반적으로이 크기는 Receive 또는 BeginReceive 메서드에서 0부터 지정된 버퍼 길이까지입니다.

그래서 BeginReceive에 100 바이트를 읽도록 지시하더라도 그보다 작은 값을 읽을 수 있으며 ??? 네트워크 지원 소프트웨어 (TCP/IP)를 개발 중이며 요청한 정확한 바이트 수를 항상받습니다.

나는 로직을 이해하지 못한다. 내가 요청한 모든 바이트를받지 못한다면 왜 Receive는 비동기 적으로 완료 될까? 그냥 계속 기다린다.

아마도 IP 대 TCP와 관련이 있습니까?

답변

2

소켓이 비동기 모드에서 작동하는 경우 소켓은 비동기 모드에서 실제로 요청한 바이트 수를 요구 한 양까지 반환하지만 요청 된 양은 최대 주어진 읽기. 매번 요청할 때마다 많은 바이트를 확보 할 수는 없습니다. 결국 필요한 바이트를 모두 얻을 때까지 계속해서 읽어야하고, 남아있는 내용을 캐시하여 나중에 더 많은 바이트를 사용할 수있게되면 나중에 처리 할 수 ​​있습니다. 바로 바딤의 예제 코드가하는 일입니다. 이 유형의 읽기는 비동기 적이므로 다른 작업을 계속하는 동안 백그라운드에서 소켓 수신 바이트가 있고 더 많은 바이트가 사용 가능할 때 사용자에게 알립니다.

당신이 생각하고있는 것은 소켓이 동기식 모드에서하는 일입니다. 코드가 작업을 계속하기 전에 요청 된 모든 바이트가 도착할 때까지 기다립니다.

0

이더넷 프레임이 도착하면 이더넷 장치 드라이버는 전체 프레임을 복사 한 후에 만 ​​전체 프레임을 메모리에 복사합니다. 그러면 상위 프레임 (TCP)에 알립니다. 그런 다음 TCP 레이어는 데이터를 버퍼로 복사하고 소켓 레이어를 호출합니다. 그런 다음 소켓 계층은 사용 가능한 데이터를 소켓 버퍼라는 버퍼 공간에 복사합니다. 마지막으로 데이터가 사용자 버퍼에 복사되고 프로세스에 신호가 보내집니다.

receive()에 의해 반환 된 데이터의 크기가 요청 된 데이터보다 작을 수있는 시나리오는 무엇입니까? 1) 이더넷 프레임이 요청한 크기보다 작은 경우 2) TCP 버퍼 크기 sysctl 매개 변수 (Linux의 경우 net.ipv4.tcp_rmem)가 요청 된 크기보다 작은 지 확인 할 수 있습니다. 3) 소켓 버퍼 크기 (SO_RCVBUF를 사용하여 응용 프로그램 별 크기, setsockopt()로 설정할 수 있음)가 요청 된 크기보다 작은 경우.

위의 시나리오 외에도 지정된 사용자 버퍼 크기가 전체 프레임을 수용 할만큼 충분히 클 경우 전체 프레임이 항상 사용자 버퍼에 복사됩니다.

IP 계층에는 여기에서 어떤 역할도하지 않습니다.

0

예, 실제로 이상한 동작입니다. 그러나, 나는 그것을 어떻게 보는지. ..그것은 틀릴 수도 있지만 세션을 디버깅 한 후 오랜 시간이 지나면 나 자신에게 설명하는 방법입니다. -/

정상적으로 수신 (동기화)을 사용하면 정상적으로 수신보다 n 바이트를 읽습니다. BeginReceive (비동기 적으로)를 사용하면 으로 시작하여 n 바이트를 읽을 때 사용자에게 전화를 겁니다.

즉, 실제로는 n 바이트를 읽으려고 시도합니다. 끝날 때 대신 수신하기 시작하면 알려줍니다. 그리고 때로는 n 바이트를 읽는 것이 불가능하지만, 불행하게도 begin 신호가 이미 호출되었습니다.

이름이 혼란 스럽다는 데 동의합니다.

행운을 빈다!

관련 문제