2010-07-19 10 views
2

난 간단한 .net 3.5sp1 윈도우 응용 프로그램 (C#에서) UDP 서버 역할을합니다. 포트에서 청취하고 엔드 포인트에서 데이터를 수신 한 다음 수신 한 데이터를 다른 엔드 포인트 (즉, 라이브 브로드 캐스트 데이터 스트림의 릴레이)로 재전송합니다. 내가 겪고있는 것은 연결이 약 20 분 동안 지속 된 후에, 악화되기 시작한 것입니다. 또한 나는 그것이 초당 약 50-100K의 메모리를 차지하고 있음을 발견했다. 이것은 GC 이후에 출시되지 않는다. 앱을 닫고 다시 시작해야합니다. 안좋다. SendToAsync 메모리 누출?

var sendBuffer = new byte[readCount]; 
Array.Copy(readData, sendBuffer, readCount); 
SocketAsyncEventArgs args = new SocketAsyncEventArgs(); 
args.RemoteEndPoint = p.EP; 
args.SetBuffer(sendBuffer, 0, sendBuffer.Length); 
SwitchWindow.LineSocket.SendToAsync(args); 

사람이 SendToAsync와 메모리 누수 어떤 경험이 있습니까

: 나는 다른쪽으로 재전송을 수행하는 다음 코드에 문제를 좁혀?

UPDATE :

내가 소켓이 초기화 된 상태 개체 (한 번만 수행)를 인스턴스화합니다. 상태 개체에는 "buffer"라는 속성이 있으며이 속성은 바이트 배열입니다. 나는 그런처럼 소켓에서 데이터 비동기가 나타납니다

private void beginReceiveData(ref MessageState state) 
{ 
    var ipeSender = new IPEndPoint(IPAddress.Any, 0); 
    var epSender = (EndPoint)ipeSender; 

    state.workSocket = LineSocket; 
    state.EP = epSender; 
    state.workSocket.BeginReceiveFrom(state.buffer, 0, MessageState.BufferSize, 
     SocketFlags.None, ref epSender, 
     new AsyncCallback(ReceiveDataCB), 
     state); 
} 

, 그때 내 콜백 (ReceiveDataCB)에, 내가 비동기 객체를 검색하고, 다음 처리를위한 또 다른 기능으로 바이트 버퍼를 통과 한 차례 통화에서 위에 게시 된 코드는 다른 쪽 (state.buffer는 readData가됩니다)으로 다시 전송합니다.

업데이트 # 2 :

내 직감에 따라, 나는 SocketAsyncEventArgs과 SendToAsync 치우는 다음에 보내는 코드를 변경 : 물론,

var sendBuffer = new byte[readCount]; 
Array.Copy(readData, sendBuffer, readCount); 
SwitchWindow.LineSocket.BeginSendTo(
    sendBuffer, 0, sendBuffer.Length, SocketFlags.None, 
    p.EP, new AsyncCallback(echoCB), null); 

을 그리고, 내가 추가 한 " echoCB "EndSendTo를 호출하는 것 외에는 아무것도 수행하지 않는 콜백. 메모리 누수가 이제 사라졌습니다! 나는 그것이 너무 많은 SocketAsyncEventArgs 객체를 생성하는 것과 관련이 있고, 비동기 함수가 각 패킷 (초당 33 패킷)에 매달려 있다고 의심한다. SocketAsyncEventArgs에 대한 MSDN 설명서를 다시 한 번 살펴 봤습니다. 서버 "예제"코드가 제공되면 SocketAsyncEventArgs 개체 풀을 사용한다는 것을 알았습니다. 나는 그것이 그것을 사용하고있는 방식대로 작동하도록 정말로 고안된 것이라고 생각하지 않는다. 전체적인 요점은 각 호출에 대해 이러한 버퍼 등을 인스턴스화 할 필요가 없으므로 재사용하고 서버의 성능을 향상시키는 것입니다.

답변

0

readData 버퍼는 어디에 할당 되었습니까?
전체 수신/송신 루프가 동일한 범위 안에 있습니까?

+0

내가 –

0

당신은 항상 아래로 개체에 대한 참조를 유지 누가 추적 할

!gcroot <address> 

사용할 수 있습니다. CLR Memory Leak을 참조하십시오.

0

나는 당신의 릴레이 노드가 훨씬 더 많은 데이터 수신 작업을하고 있으며 궁극적으로 데이터를 전송하는 것보다 더 빨리 수신한다고 생각한다. 데이터가 유선에서 벗어남에 따라 메모리를 할당하고 비동기 적으로 전송되도록 대기열에 올려 놓습니다. 그러나 보내는 데이터가 새 데이터를 수신하는 데 (그리고 할당하는 것보다) 훨씬 느리게 전송되어 과부하가 발생합니다 들어오는 데이터. 이는 업로드 속도보다 다운로드 속도가 빠른 네트워크 노드에서 자주 발생합니다.

수락하고 할당 할 수있는 수신 데이터의 양을 조절할 수 있습니다. 콜백을 사용하면이 작업을 수행 할 수 있습니다 (args.(콜백에서 전송 된 추적을 통해) 실제로 전송 된 데이터와 전송 대기중인 데이터의 양을 추적하여 완료합니다 (). 전송 대기중인 데이터의 양이 임의의 한계보다 큰 경우 새 데이터를 승인하지 마십시오.

스트리밍 비디오를하는 경우 프레임을 건너 뛰거나 전체 패킷을 버려야 할 수 있습니다.

+0

좋은 생각을 게시 내 편집을 참조하십시오. 스트리밍 오디오를하고 있지만 뒤늦게 또는 건너 뛰지 않습니다. 사실, 나는 바이트/아웃을 모니터링하고 있으며 그것들은 동일하다. 전송으로 인해 약 1/3 초 지연을 유지할 수 있습니다. –

5

당신은 아마 SocketAsyncEventArgs.Dispose를 호출하지 않습니다()는