3

Socket.BeginReceive(...)とSocket.EndReceive(...)をUDPパケットレシーバークライアントとして使用しようとしています。期待どおりにパケットを受信して​​処理しますが、ソケットをキャンセルしてシャットダウンしたい場合、実装したClose()関数はSocket.EndReceive(...)で終了します。スレッドで例外がスローされたと思いますが、例外をキャッチして問題が何であるかを確認する方法がわかりません。以前、Socket.EndReceive(...)を使用して、SocketErrorがSuccessとして返されました。これは、私がソケットをどのように使用しているかを示すコードです。

更新されたコード

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();
}
4

1 に答える 1

4

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();
}
于 2012-12-17T06:56:51.557 に答える