【问题标题】:receiveTimeout Breaks the communication channel after inactivity?receiveTimeout 在不活动后中断通信通道?
【发布时间】:2026-01-30 08:45:01
【问题描述】:

嗨,

我有一个托管在 IIS 中的 WCF 服务,它具有以下绑定配置:

 <binding name="netTcpRegular" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:00:20" sendTimeout="00:20:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxConnections="10" maxReceivedMessageSize="2147483647">
          <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
          <reliableSession ordered="true" inactivityTimeout="infinite" enabled="false"/>
          <security mode="None">
            <transport clientCredentialType="None" />
          </security>
        </binding>

当客户端(保持通道打开)登录到 WCF 服务时,通道将在 20 秒后抛出错误异常,而我什么都不做,甚至没有与服务通信?所以在 20 秒不活动后,通信将失败。

receiveTimeout 应该只影响通话进行的时间,对吧?那么,除了让通道打开并准备好进行服务调用之外什么都不做时,它怎么会超时呢?

编辑:

通过使用 WCF 日志,我得到了以下异常:

<DataItem>
<TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Error">
<TraceIdentifier>http://msdn.microsoft.com/sv-SE/library/System.ServiceModel.Diagnostics.ThrowingException.aspx</TraceIdentifier>
<Description>Throwing an exception.</Description>
<AppDomain>/LM/W3SVC/1/ROOT/MyTest-1-129811288584315020</AppDomain>
<Exception>
<ExceptionType>System.ServiceModel.CommunicationException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '10675199.02:48:05.4775807'.</Message>
<StackTrace>
at System.ServiceModel.Channels.SocketConnection.EndRead()
at System.ServiceModel.Channels.PreReadConnection.EndRead()
at System.ServiceModel.Channels.DelegatingConnection.EndRead()
at System.ServiceModel.Channels.DelegatingConnection.EndRead()
at System.ServiceModel.Channels.TracingConnection.EndRead()
at System.ServiceModel.Channels.SessionConnectionReader.OnAsyncReadComplete(Object state)
at System.ServiceModel.Channels.TracingConnection.TracingConnectionState.ExecuteCallback()
at System.ServiceModel.Channels.TracingConnection.WaitCallback(Object state)
at System.ServiceModel.Channels.SocketConnection.FinishRead()
at System.ServiceModel.Channels.SocketConnection.AsyncReadCallback(Boolean haveResult, Int32 error, Int32 bytesRead)
at System.ServiceModel.Channels.OverlappedContext.CompleteCallback(UInt32 error, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</StackTrace>
<ExceptionString>System.ServiceModel.CommunicationException: The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '10675199.02:48:05.4775807'. ---&gt; System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
   --- End of inner exception stack trace ---</ExceptionString>
<InnerException>
<ExceptionType>System.Net.Sockets.SocketException, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>An existing connection was forcibly closed by the remote host</Message>
<StackTrace>
at System.ServiceModel.Channels.SocketConnection.EndRead()
at System.ServiceModel.Channels.PreReadConnection.EndRead()
at System.ServiceModel.Channels.DelegatingConnection.EndRead()
at System.ServiceModel.Channels.DelegatingConnection.EndRead()
at System.ServiceModel.Channels.TracingConnection.EndRead()
at System.ServiceModel.Channels.SessionConnectionReader.OnAsyncReadComplete(Object state)
at System.ServiceModel.Channels.TracingConnection.TracingConnectionState.ExecuteCallback()
at System.ServiceModel.Channels.TracingConnection.WaitCallback(Object state)
at System.ServiceModel.Channels.SocketConnection.FinishRead()
at System.ServiceModel.Channels.SocketConnection.AsyncReadCallback(Boolean haveResult, Int32 error, Int32 bytesRead)
at System.ServiceModel.Channels.OverlappedContext.CompleteCallback(UInt32 error, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</StackTrace>
<ExceptionString>System.Net.Sockets.SocketException (0x80004005): An existing connection was forcibly closed by the remote host</ExceptionString>
<NativeErrorCode>2746</NativeErrorCode>
</InnerException>
</Exception>
</TraceRecord>
</DataItem>

<TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Error">
<TraceIdentifier>http://msdn.microsoft.com/sv-SE/library/System.ServiceModel.Diagnostics.ThrowingException.aspx</TraceIdentifier>
<Description>Throwing an exception.</Description>
<AppDomain>/LM/W3SVC/1/ROOT/MyTest-1-129811288584315020</AppDomain>
<Exception>
<ExceptionType>System.ServiceModel.CommunicationException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '10675199.02:48:05.4775807'.</Message>
<StackTrace>
at System.ServiceModel.Channels.SocketConnection.EndRead()
at System.ServiceModel.Channels.PreReadConnection.EndRead()
at System.ServiceModel.Channels.DelegatingConnection.EndRead()
at System.ServiceModel.Channels.DelegatingConnection.EndRead()
at System.ServiceModel.Channels.TracingConnection.EndRead()
at System.ServiceModel.Channels.SessionConnectionReader.OnAsyncReadComplete(Object state)
</StackTrace>
<ExceptionString>System.ServiceModel.CommunicationException: The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '10675199.02:48:05.4775807'. ---&gt; System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
   --- End of inner exception stack trace ---
   at System.ServiceModel.Channels.SocketConnection.EndRead()
   at System.ServiceModel.Channels.PreReadConnection.EndRead()
   at System.ServiceModel.Channels.DelegatingConnection.EndRead()
   at System.ServiceModel.Channels.DelegatingConnection.EndRead()
   at System.ServiceModel.Channels.TracingConnection.EndRead()
   at System.ServiceModel.Channels.SessionConnectionReader.OnAsyncReadComplete(Object state)</ExceptionString>
<InnerException>
<ExceptionType>System.Net.Sockets.SocketException, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>An existing connection was forcibly closed by the remote host</Message>
<StackTrace>
at System.ServiceModel.Channels.SessionConnectionReader.GetPendingMessage()
at System.ServiceModel.Channels.SessionConnectionReader.EndReceive()
at System.ServiceModel.Channels.SynchronizedMessageSource.ReceiveAsyncResult.OnReceiveComplete(Object state)
at System.ServiceModel.Channels.SessionConnectionReader.OnAsyncReadComplete(Object state)
at System.ServiceModel.Channels.TracingConnection.TracingConnectionState.ExecuteCallback()
at System.ServiceModel.Channels.TracingConnection.WaitCallback(Object state)
at System.ServiceModel.Channels.SocketConnection.FinishRead()
at System.ServiceModel.Channels.SocketConnection.AsyncReadCallback(Boolean haveResult, Int32 error, Int32 bytesRead)
at System.ServiceModel.Channels.OverlappedContext.CompleteCallback(UInt32 error, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</StackTrace>
<ExceptionString>System.Net.Sockets.SocketException (0x80004005): An existing connection was forcibly closed by the remote host</ExceptionString>
<NativeErrorCode>2746</NativeErrorCode>
</InnerException>
</Exception>
</TraceRecord>

编辑:

客户端绑定:

<binding name="NetTcpBinding_IMyClientServiceRegular" closeTimeout="00:01:00" openTimeout="00:00:30" receiveTimeout="00:00:30" sendTimeout="00:00:30" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxConnections="10" maxReceivedMessageSize="2147483647">
  <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
  <reliableSession ordered="true" inactivityTimeout="infinite" enabled="false"/>
  <security mode="None">
    <transport clientCredentialType="None"/>
  </security>
</binding>

【问题讨论】:

  • 你的客户端绑定配置是什么?
  • this SO post的可能重复
  • 似乎您已将 recieveTimeout (receiveTimeout="00:00:20" ) 设置为 20 秒,因此服务器正在断开连接。你能设置一个高于 20 秒的值吗?
  • 是的,我已经尝试过了,它解决了问题,但我不明白,receiveTimeout 是根据 MSDN 的说法,一个电话可能需要多长时间才能接收,对我来说,这意味着如果我发送一个2GB 大小的消息然后我将不得不增加 reveiveTimout 因为数据需要一些时间才能发送到网络。在这种情况下,我什么都不做?从最后一次调用服务开始 20 秒后,我会得到异常吗?这听起来更像是 inactivityTimeout?
  • 我确实有一个 keepAlive 操作,从客户端到服务每 9 分钟调用一次,以保持连接处于活动状态,但这不会在 20 秒内触发。

标签: wcf timeout


【解决方案1】:

您误解了meaning of ReceiveTimeout。它是“连接可以保持非活动状态的时间间隔,在此期间没有收到应用程序消息,在它被丢弃之前”。要将其扩展到无穷大,您需要enable reliable sessions。希望这能解决问题。

编辑: Here 是进一步的描述,我认为你所追求的属性是 sendtimeout

【讨论】:

  • 附注recievetimeout 属性的默认值为 10 分钟
  • 可以将ReceiveTimout设置为无限,这是我之前使用的设置,但感觉不对。但是,如果我需要长时间的会话,那么这是我应该使用的唯一设置。
  • @SnowJim 是的,这是使会话“持久”所需的设置
  • 根据 MSDN 文档使用 TCP 绑定时不需要 reliableSession。
  • @SnowJim 请给我一个链接
【解决方案2】:

接收超时是等待接收所有数据的时间。

通道一打开,时间就开始计时,它不会检测到您发送的第一个字节,然后启动计时器。

这有点像出租车,它会在你挥下计程表时启动,而不是在你上车时启动。

【讨论】: