3

我有一个用于发布/订阅模式的双工 WCF 通道。我无法弄清楚如何在不产生跟踪错误的情况下干净地断开客户端。该错误不会影响应用程序,但会显示在跟踪日志中。由于这个预期的错误消息正在填满我们的日志,因此很难找出其他问题。

服务器端日志中显示的错误:

“现有连接被远程主机强行关闭” System.ServiceModel.Channels.SocketConnection.HandleReceiveAsyncCompleted() System.ServiceModel.Channels.SocketConnection.OnReceiveAsync(Object sender, SocketAsyncEventArgs eventArgs) System.Net.Sockets.SocketAsyncEventArgs.FinishOperationAsyncFailure(SocketError socketError, Int32 bytesTransferred, SocketFlags flags) System.Net.Sockets.SocketAsyncEventArgs.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped) System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

server code:
        public static void StartHost()
        {
           var startTime = DateTime.Now;
        var duplex = new ServiceHost(typeof(HostChannel));
        try
        {
            duplex.AddServiceEndpoint(typeof(IHostChannel),
                CreateTpcBinding(),
               AppConfiguration.SchedulerHostChannel);
            duplex.Open();

            _duplex = duplex;

        }
        catch (Exception e)
        {
            log.LogError("Error acquiring HostChannel:" + e);
            if (duplex.State == CommunicationState.Faulted)
                duplex.Abort();
            duplex.Close();
            throw;
        }
    }

private static NetTcpBinding CreateTpcBinding()
    {
        return new NetTcpBinding()
        {
            ReliableSession = new OptionalReliableSession() { InactivityTimeout = TimeSpan.FromDays(5) },
            ReceiveTimeout = TimeSpan.FromDays(5),
            ReaderQuotas = new XmlDictionaryReaderQuotas() { MaxStringContentLength = 5242880 }
        };
    }
    /// <summary>
    /// First method the client calls 
    /// </summary>
    public void EstablishConnection()
    {
        var channelBinder = ServiceLocator.Current.GetInstance<RemoteResourceManager>();
        var remoteChannel = OperationContext.Current.GetCallbackChannel<IRemoteChannel>();
        _processHandle = channelBinder.RegisterRemoteChannel(remoteChannel);
    }
    /// <summary>
    /// Last method that is called
    /// </summary>
    public void NotifyComplete()
    {
        _processHandle.Events.OnCompleted(_processHandle.RemoteChannel, new EventArgs());


        log.LogInfo("Try to clean callback channel");
        ((IClientChannel)_processHandle.RemoteChannel).Close();
        ((IClientChannel)OperationContext.Current.GetCallbackChannel<IRemoteChannel>()).Close();
        log.LogInfo("Cleaned callback channel");


    }

客户端回调接口:

public interface IRemoteChannel
{
    [OperationContract(IsOneWay = true)]
    void StartTask(TaskDefinition taskDefinition);
    [OperationContract(IsOneWay = true)]
    void RequestCancelTask();
    [OperationContract(IsOneWay = true)]
    void HealthCheck();
} 

调用 NotifyComplete 后客户端清理代码

 if (_proxy is IClientChannel)
            channel = ((IClientChannel)_proxy);

        try
        {
            if (channel != null)
            {
                if (channel.State != CommunicationState.Faulted)
                {
                    channel.Close();
                }
                else
                {
                    channel.Abort();
                }
            }
        }
        catch (CommunicationException e)
        {
            channel.Abort();
        }
        catch (TimeoutException e)
        {
            channel.Abort();
        }
        catch (Exception e)
        {
            channel.Abort();
            throw;
        }
        finally
        {
            _proxy = null;
        }
4

0 回答 0