2009-09-10 3 views
1

네트워크에서 읽은 버퍼링 데이터를 처리하는 방법?

네트워크를 통해 데이터를 읽을 때 데이터를받을 버퍼를 지정합니다.

byte[] b = new byte[4096]; 
socket.Receive(b); 

이제 첫 번째 생각은 물론 클래스의 멤버 변수로 선언하여 수신 버퍼를 다시 사용하는 것입니다. 다음 문제는 내가 기대하고있는 모든 데이터를받지 못했기 때문에 데이터를 버퍼링해야한다는 것입니다. 수신 한 바이트 수를 추적하고 오프셋을 지정하면 쉽게 달성 할 수 있습니다.

socket.Receive(m_ReceiveBuffer, count, m_ReceiveBuffer.Length - count); 

여기서 문제는 여전히 충분하지 않은 경우, buffer는 메모리를 복사하고이 버퍼로 계속 수신하는 것을 의미합니다. 무언가 잘못되었다고 가정하면이 버퍼는 계속 커질 것이며 메시지가 충분히 크면 메모리가 부족한 시스템을 실행하게됩니다.

어떤 아이디어를 제대로 처리하는 방법? 내가 말하는 그저 채우기, 복사, 성장, 채우기, 복사, 성장하는 것보다 더 나은 데이터 수신 방법이 있습니까?

답변

2

읽기 :

const int ChunkSize = 4096; 
int bytesRead; 
byte[] buffer = new byte[ChunkSize]; 
while ((bytesRead = socket.Receive(buffer, 0, ChunkSize, SocketFlags.None)) > 0) 
{ 
    byte[] actualBytesRead = new byte[bytesRead]; 
    Buffer.BlockCopy(buffer, 0, actualBytesRead, 0, bytesRead); 
    // Do something with actualBytesRead, 
    // maybe add it to a list or write it to a stream somewhere 
} 
+0

아직도 데이터를 처리 할 수없는 문제가 해결되지 않고 있으며, 메모리를 계속 채울 것입니다. – esac

+0

데이터를 "처리"한다는 것이 무슨 뜻인지 설명해 주시겠습니까? 청크로 데이터를 "처리"할 수 없습니까? 물론 모든 데이터를 읽어야 할 필요가 있습니까? 물론 메모리에 저장해야 할 필요가 있습니까? –

1

을 System.Net.Sockets.Socket으로 시작하기 전에, 당신은 당신이 System.Net.Sockets.TcpClient (또는 UdpClient)를 사용할 수 있는지 확인 수있는 모든 않습니다 어수선한 버퍼가 작동하고 쉽게 관리되는 스트림으로 변환됩니까?

그렇지 않은 경우 수신하는 데이터의 양이 요청한 것과 동일 할 필요는 없으므로 항상 수신 기능의 반환 값을 확인해야합니다. 그리고 메모리가 부족하지 않게하는 유일한 방법은 실제로 처리하는 것입니다.

+0

예, Receive를 예로만 사용하지만 ReceiveAsync API를 사용하여 비동기 방식으로 데이터를 읽습니다. 이를 위해 내 경우에는 네트워크 스트림이 작동하지 않습니다. 그리고 내 문제는 모든 데이터를 즉시 처리 할 수 ​​있다면 좋지만 때로는 조금 더 크게하기에 충분하다는 것입니다. – esac

0

먼저 코드를 분리하여 데이터를 수신하고 데이터를 처리합니다. 수신 버퍼는 코드가 처리 영역으로 데이터를 복사 할 수있을 때까지만 데이터를 보유해야합니다. 처리 영역은 유용하게 사용할 수있는 충분한 데이터를 받았는지 여부를 결정하는 곳입니다. 이 때까지 네트워크 수신 버퍼에 데이터를 남기지 마십시오. 네트워크 수신 버퍼의 경우 원형 버퍼를 사용하면 버퍼 재사용에 도움이 될 것입니다. 다행히도 메시지 크기에 대한 아이디어가 있습니다. 버퍼의 크기를 결정하는 데 도움이됩니다. 순환 버퍼의 읽기 및 쓰기 포인터가 만날 때 (또는 비슷한) 주장하면 버퍼의 크기를 늘리십시오. 버퍼의 크기가 충분히 크면 순환 버퍼가 오버플로하지 않을만큼 충분히 빠른 속도로 버퍼에서 처리 코드로 충분한 데이터를 읽을 수 있어야합니다.

관련 문제