2012-12-17 4 views
2

Socket.BeginReceive (...) 및 Socket.EndReceive (...)를 UDP 패킷 수신기 클라이언트로 사용하려고합니다. 그것은 예상대로 패킷을 받고 처리하지만 소켓을 취소하고 종료 할 때 구현 된 Close() 함수는 Socket.EndReceive (...) 함수를 종료합니다. 스레드에서 예외가 throw 된 가정 있지만 문제가 무엇인지 보려면 예외를 catch하는 방법을 알아낼 수 없습니다. Success로 반환되는 SocketError와 함께 Socket.EndReceive (...)를 사용했습니다. 다음은 소켓을 어떻게 사용하는지 보여주는 코드입니다.Socket.EndReceive (...)가 제대로 반환되지 않습니다.

업데이트 코드

void _startReceiving() 
{ 
    _buffer = new byte[Marshal.SizeOf(typeof(EthernetShare.Message))]; 
    _receiveResult = _udpSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, messageProcessor, null); 
} 

private void messageProcessor(IAsyncResult result) 
{ 
    int packetSize = _udpSocket.EndReceive(result); 
    if (packetSize == _buffer.Length) 
    { 
     byte[] packet = _buffer; 
     IAsyncResult asyncResult = result; 
     _startReceiving(); 
     OnMessageReceieved(_buffer.ToStruct<DataStreamingMessage>()); 
    } 
} 
public void Stop() 
{ 

    _continue = false; 
    SocketError error; 
    try 
    { 
     int tmp = _udpSocket.EndReceive(_receiveResult, out error); 

    } 
    catch (Exception) 
    { 

     throw; 
    } 
    _udpSocket.Close(); 
} 

기존 코드

private Socket _udpSocket; 
private byte[] _buffer; 
private IAsyncResult _receiveResult; 
void _startReceiving() 
{ 
    byte[] buffer = new byte[Marshal.SizeOf(typeof(EthernetShare.Message))]; 
    _receiveResult = _udpSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, messageProcessor, null); 
    //_receiveResult = _udpSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, messageProcessor, _continue); 
} 

private void messageProcessor(IAsyncResult result) 
{ 

    //if ((bool)result.AsyncState && result.IsCompleted) 
    if (result.IsCompleted) 
    { 
     _buffer = new byte[Marshal.SizeOf(typeof (EthernetShare.Message))]; 
     //_receiveResult = _udpSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, messageProcessor, _continue); 
     _receiveResult = _udpSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, messageProcessor, null); 
    } 
} 


public void Stop() 
{ 

    _continue = false; 
    SocketError error; 
    try 
    { 
     int tmp = _udpSocket.EndReceive(_receiveResult, out error); 

    } 
    catch (Exception) 
    { 

     throw; 
    } 
    _udpSocket.Close(); 
} 

답변

3

APM (비동기 프로그래밍 모델)의 사용이 잘못되었습니다. 참조 : http://msdn.microsoft.com/en-us/library/ms228963.aspx

BeginXXX에 대한 각 호출은 EndXXX와 일치해야합니다.

는 의사 코드에서는 다음과 같이 보일 수 있습니다 의미가

private bool isClosed; 
private Socket socket; 

void BeginReceiveNextPacket(){ 
    socket.BeginReceive(..., EndReceiveNextPacket); 
} 

void EndReceiveNextPacket(IAsyncResult result){ 
    try{ 
     // By making a call to EndReceive, we allow the socket to wrap up, close internal handles and raise any exceptions if they exist. 
     socket.EndReceive(result); 

     // Now make a new call to BeginReceive after we invoked the actual call to EndReceive. 
     BeginReceiveNextPacket(); 
    } 
    catch(SocketClosedException) { 
     if (closed){ 
      // We forcefully closed this socket. Therefore, this exception was expected and we can ignore it. 
     } 
     else{ 
      throw; // Catch an unexpected exception. 
     } 
    } 
} 

void Stop(){ 
    isClosed = true; 
    socekt.Close(); 
} 
+0

감사합니다, 모든이 끝과 시작 페어링 때 여전히 문제가 있지만. 내 새 업데이트를 표시하는 업데이트를 게시했습니다. – galford13x

+0

EndReceive를 여러 번 호출 할 수 없습니다. close 메소드에서 EndReceive와 콜백을 호출합니다. 이 충돌. 현재 요청이 완료 될 때까지 닫기 메소드에서 기다리고 싶다면 _recieveResult에있는 WaitHandle을 사용하여 대기 할 수 있습니다. – Polity

+0

실제로 무슨 뜻인지 알 것입니다. Stop 함수에서 EndReceive를 제거했습니다. 여기에 문제가 있습니다. 클라이언트는 항상 소켓을 닫을 때 더 많은 데이터가 전달 될 것이라고 가정합니다. messageProcessor가 실행되고 EndReceive를 실행하려고하면 ObjectDisposedException이 throw됩니다. 어떤 이유로 셧다운이 적절하지 않은 것으로 보입니다. – galford13x

관련 문제