我正在使用WCF流式传输文件从WCF客户端转移到netTcpBinding
的服务。
一旦客户端使用Stream实例调用服务,服务将开始通过套接字连接(StreamConnection
)从Stream实例读取。但是,如果在服务端从流读取的过程中发生异常,则客户端不能立即获得异常。
我发现延迟期与sendTimeout
绑定有关。如果我设置sendTimeout=20 seconds
,客户端会在20秒延迟时获得异常;如果sendTimeout = 1 second
,客户端立即获得异常。
我做了一些研究。我的理解是,即使在服务上抛出异常,它也不会抛出客户端,直到StreamConnection.Read()/StreamConnection.Write()
为止。此超时期限与绑定sendTimeout同步。
是否可以保留sendTimeout
并让客户端立即获得异常?
这是服务绑定,(为了传输大尺寸的文件,我更改了maxReceivedMessageSize,sendTimeout和receiveTimeout等的值)
<netTcpBinding>
<binding name="StreamingNetTCPBinding" transferMode="Streamed" maxConnections="500" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" sendTimeout="00:45:00" receiveTimeout="23:00:00" listenBacklog="20">
<readerQuotas maxArrayLength="2147483647" maxDepth="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" maxStringContentLength="2147483647" />
</binding>
</netTcpBinding>
答案 0 :(得分:0)
您看到的行为是由于流模式与缓冲相比的语义。使用缓冲连接时,即使使用请求/回复,它实际上也是双工连接。始终发布待处理接收以接受传入请求或回复任何未完成的请求。这就是为什么您可以通过单个通道从多个线程在单个NetTcp连接上发送多个未完成的请求。对于流模式,当发出请求时,呼叫实例拥有该信道,直到呼叫完成。发送请求流,并且只有在发送请求流之后,我们才会在连接上发出接收/读取。这是因为如果请求消息实际上没有完全发送,即使响应消息是故障消息,也无法对请求消息进行回复。
根据您的要求,您可以选择如何处理此问题,其中大部分内容仅需要在服务代码中进行更改。在服务端,如果抛出异常,则需要捕获异常,排空传入流,然后重新抛出异常,这将导致返回Fault消息。当响应流被完全读取时,客户端已完成它的所有发送,现在正在等待响应。这确实需要发送整个请求流,并且在大量请求提前失败的情况下,这可能是不合需要的。如果不希望花费时间/带宽来接收消息的其余部分,那么您可能会在服务端错误地使用通道(使用Abort())。这将导致套接字断开连接,您将在客户端获得CommunicationException。这样做的缺点是没有收到有关出错的信息,但会很快。
另一个需要在客户端和服务器端进行更改的选项是使用两个通道,并使用第二个通道接收有关第一个通道上请求状态的OOB信息。