{"id":2154,"date":"2012-09-26T15:34:22","date_gmt":"2012-09-26T15:34:22","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/webdev\/2012\/09\/26\/wcf-duplex-bi-directional-streaming-with-websocket-transport\/"},"modified":"2022-08-10T06:11:09","modified_gmt":"2022-08-10T13:11:09","slug":"wcf-duplex-bi-directional-streaming-with-websocket-transport","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/wcf-duplex-bi-directional-streaming-with-websocket-transport\/","title":{"rendered":"WCF Duplex Bi-directional Streaming with WebSocket Transport"},"content":{"rendered":"<div id=\"scid:fb3a1972-4489-4e52-abe7-25a00bb07fdf:7736a7de-2d53-4404-96b1-45da49fab7a9\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<p>DuplexBiDirectionalStreaming VS2012 project <a href=\"https:\/\/devblogs.microsoft.com\/00\/00\/00\/63\/56\/metablogapi\/4478.DuplexBiDirectionalStreaming_46B811B8.zip\" target=\"_blank\" rel=\"noopener\">DuplexBiDirectionalStreaming.zip<\/a><\/p>\n<\/div>\n<h3>Introduction<\/h3>\n<p>With WebSocket transport, it\u2019s possible to use streamed transport on the Duplex Callback \u2013 something that was previously a technical limitation with WCF but is now possible using this transport. New to .Net4.5 is the NetHttpBinding (and NetHttpsBinding), which is a new standard binding that leverages the WebSocket transport if it makes sense to do so. You can configure it to always use WebSocket transport, but by default, it will only use it for Duplex channel shapes. Why? Well, what this transport gives you is the ability for the server to push data to the client without an incoming request. If your contract is already request-reply, there isn\u2019t much increase in efficiency by using the WebSocket transport. But with duplex, there isn\u2019t necessarily a 1-1 correspondence with requests and replies. Of course, the binding does give you the ability to change this setting.<\/p>\n<h3>Requirements<\/h3>\n<p>WebSocket transport is only possible on the Windows8 operating system. I\u2019m using Windows8 for this demo with Visual Studio 2012. IIS needs to be installed, with full support for Http Activation and WebSocket Transport. To run the service in IIS from Visual Studio, you need to run Visual Studio as an administrator.<\/p>\n<h3>Walk-Through<\/h3>\n<p>First, I created a new Console Project in Visual studio. This will be the client. I\u2019ll leave it alone for now, and add a WCF service:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2012\/09\/4863.clip_image002_thumb_25C49F11.jpg\"><img decoding=\"async\" title=\"clip_image002\" border=\"0\" alt=\"clip_image002\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2012\/09\/4863.clip_image002_thumb_25C49F11.jpg\" width=\"460\" height=\"321\" \/><\/a><\/p>\n<p>Next, I\u2019ll define the service contract. I want to be able to upload bytes for as long as I want. Also, I want to be able to download bytes at the same time, and have a way to tell the service to stop sending me bytes. I\u2019ll also put something in there to grab logs from the service implementation. I created this in a new class library so it can be shared between the client and service.<\/p>\n<div id=\"scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:ba5fdf40-034b-4104-8602-6eb48920fd67\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<div style=\"border: #000080 1px solid;color: #000;font-family: 'Courier New', Courier, Monospace;font-size: 10pt\">\n<div style=\"background: #000080;color: #fff;font-family: Verdana, Tahoma, Arial, sans-serif;font-weight: bold;padding: 2px 5px\">Code Snippet<\/div>\n<div style=\"background: #ddd;max-height: 300px;overflow: auto\">\n<ol start=\"1\" style=\"background: #ffffff;margin: 0 0 0 2.5em;padding: 0 0 0 5px\">\n<li><span style=\"background:#ffffff;color:#000000\">[<\/span><span style=\"background:#ffffff;color:#2b91af\">ServiceContract<\/span><span style=\"background:#ffffff;color:#000000\">(CallbackContract = <\/span><span style=\"background:#ffffff;color:#0000ff\">typeof<\/span><span style=\"background:#ffffff;color:#000000\">(<\/span><span style=\"background:#ffffff;color:#2b91af\">IClientCallback<\/span><span style=\"background:#ffffff;color:#000000\">))]<\/span><\/li>\n<li style=\"background: #f3f3f3\"><span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">public<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#0000ff\">interface<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#2b91af\">IStreamService<\/span><\/li>\n<li><span style=\"background:#ffffff;color:#000000\">{<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">[<\/span><span style=\"background:#ffffff;color:#2b91af\">OperationContract<\/span><span style=\"background:#ffffff;color:#000000\">(IsOneWay = <\/span><span style=\"background:#ffffff;color:#0000ff\">true<\/span><span style=\"background:#ffffff;color:#000000\">)]<\/span><\/li>\n<li>\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">void<\/span><span style=\"background:#ffffff;color:#000000\"> UploadStream(<\/span><span style=\"background:#ffffff;color:#2b91af\">Stream<\/span><span style=\"background:#ffffff;color:#000000\"> stream);<\/span><\/li>\n<li style=\"background: #f3f3f3\">&nbsp;<\/li>\n<li>\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">[<\/span><span style=\"background:#ffffff;color:#2b91af\">OperationContract<\/span><span style=\"background:#ffffff;color:#000000\">(IsOneWay = <\/span><span style=\"background:#ffffff;color:#0000ff\">true<\/span><span style=\"background:#ffffff;color:#000000\">)]<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">void<\/span><span style=\"background:#ffffff;color:#000000\"> StartDownloadingStream();<\/span><\/li>\n<li>&nbsp;<\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">[<\/span><span style=\"background:#ffffff;color:#2b91af\">OperationContract<\/span><span style=\"background:#ffffff;color:#000000\">(IsOneWay = <\/span><span style=\"background:#ffffff;color:#0000ff\">true<\/span><span style=\"background:#ffffff;color:#000000\">)]<\/span><\/li>\n<li>\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">void<\/span><span style=\"background:#ffffff;color:#000000\"> StopDownloadingStream();<\/span><\/li>\n<li style=\"background: #f3f3f3\">&nbsp;<\/li>\n<li>\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">[<\/span><span style=\"background:#ffffff;color:#2b91af\">OperationContract<\/span><span style=\"background:#ffffff;color:#000000\">(IsOneWay = <\/span><span style=\"background:#ffffff;color:#0000ff\">true<\/span><span style=\"background:#ffffff;color:#000000\">)]<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">void<\/span><span style=\"background:#ffffff;color:#000000\"> DownloadLog();<\/span><\/li>\n<li><span style=\"background:#ffffff;color:#000000\">}<\/span><\/li>\n<\/ol><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<p>Remember, this is duplex, so all the service operations return void. Anything that needs to go to the client goes through the callback channel, defined by this:<\/p>\n<div id=\"scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:b03eba21-555e-4788-94c9-c8a8ed72e485\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<div style=\"border: #000080 1px solid;color: #000;font-family: 'Courier New', Courier, Monospace;font-size: 10pt\">\n<div style=\"background: #000080;color: #fff;font-family: Verdana, Tahoma, Arial, sans-serif;font-weight: bold;padding: 2px 5px\">Code Snippet<\/div>\n<div style=\"background: #ddd;max-height: 300px;overflow: auto\">\n<ol start=\"1\" style=\"background: #ffffff;margin: 0 0 0 2em;padding: 0 0 0 5px\">\n<li><span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">public<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#0000ff\">interface<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#2b91af\">IClientCallback<\/span><\/li>\n<li style=\"background: #f3f3f3\"><span style=\"background:#ffffff;color:#000000\">{<\/span><\/li>\n<li>\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">[<\/span><span style=\"background:#ffffff;color:#2b91af\">OperationContract<\/span><span style=\"background:#ffffff;color:#000000\">(IsOneWay = <\/span><span style=\"background:#ffffff;color:#0000ff\">true<\/span><span style=\"background:#ffffff;color:#000000\">)]<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">void<\/span><span style=\"background:#ffffff;color:#000000\"> ReceiveStream(<\/span><span style=\"background:#ffffff;color:#2b91af\">Stream<\/span><span style=\"background:#ffffff;color:#000000\"> stream);<\/span><\/li>\n<li>&nbsp;<\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">[<\/span><span style=\"background:#ffffff;color:#2b91af\">OperationContract<\/span><span style=\"background:#ffffff;color:#000000\">(IsOneWay = <\/span><span style=\"background:#ffffff;color:#0000ff\">true<\/span><span style=\"background:#ffffff;color:#000000\">)]<\/span><\/li>\n<li>\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">void<\/span><span style=\"background:#ffffff;color:#000000\"> ReceiveLog(<\/span><span style=\"background:#ffffff;color:#2b91af\">List<\/span><span style=\"background:#ffffff;color:#000000\">&lt;<\/span><span style=\"background:#ffffff;color:#0000ff\">string<\/span><span style=\"background:#ffffff;color:#000000\">&gt; log);<\/span><\/li>\n<li style=\"background: #f3f3f3\"><span style=\"background:#ffffff;color:#000000\">}<\/span><\/li>\n<\/ol><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<p>Now, to implement the service. To do this, I\u2019ll need some kind of custom stream implementation. For demonstration purposes, I\u2019ll use a stream implementation that sends random bytes and can be turned on or off manually or configured to send for a given duration. In order to not blow MaxReceivedMessageSize buffers, I\u2019ll make a configurable throttle on it. The code for this FlowControlledStream can be found in the attached project.<\/p>\n<p>See the attached project for the full service implementation, but the new thing here is sending a stream on a callback; previously not possible with WCF. Also in there is the implementation of StopDownloadingStream.<\/p>\n<div id=\"scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:aa6521b3-e281-476e-b42f-7648b4815636\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<div style=\"border: #000080 1px solid;color: #000;font-family: 'Courier New', Courier, Monospace;font-size: 10pt\">\n<div style=\"background: #000080;color: #fff;font-family: Verdana, Tahoma, Arial, sans-serif;font-weight: bold;padding: 2px 5px\">Code Snippet<\/div>\n<div style=\"background: #ddd;max-height: 300px;overflow: auto\">\n<ol start=\"1\" style=\"background: #ffffff;margin: 0 0 0 2.5em;padding: 0 0 0 5px\">\n<li><span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">public<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#0000ff\">void<\/span><span style=\"background:#ffffff;color:#000000\"> StartDownloadingStream()<\/span><\/li>\n<li style=\"background: #f3f3f3\"><span style=\"background:#ffffff;color:#000000\">{<\/span><\/li>\n<li>\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">log.Add(<\/span><span style=\"background:#ffffff;color:#0000ff\">string<\/span><span style=\"background:#ffffff;color:#000000\">.Format(<\/span><span style=\"background:#ffffff;color:#a31515\">&quot;[{0}] StartDownloadingStream Invoked.&quot;<\/span><span style=\"background:#ffffff;color:#000000\">, <\/span><span style=\"background:#ffffff;color:#2b91af\">DateTime<\/span><span style=\"background:#ffffff;color:#000000\">.Now.Minute + <\/span><span style=\"background:#ffffff;color:#a31515\">&quot;:&quot;<\/span><span style=\"background:#ffffff;color:#000000\"> + <\/span><span style=\"background:#ffffff;color:#2b91af\">DateTime<\/span><span style=\"background:#ffffff;color:#000000\">.Now.Second + <\/span><span style=\"background:#ffffff;color:#a31515\">&quot;.&quot;<\/span><span style=\"background:#ffffff;color:#000000\"> + <\/span><span style=\"background:#ffffff;color:#2b91af\">DateTime<\/span><span style=\"background:#ffffff;color:#000000\">.Now.Millisecond));<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#2b91af\">IClientCallback<\/span><span style=\"background:#ffffff;color:#000000\"> clientCallbackChannel = <\/span><span style=\"background:#ffffff;color:#2b91af\">OperationContext<\/span><span style=\"background:#ffffff;color:#000000\">.Current.GetCallbackChannel&lt;<\/span><span style=\"background:#ffffff;color:#2b91af\">IClientCallback<\/span><span style=\"background:#ffffff;color:#000000\">&gt;();<\/span><\/li>\n<li>\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#2b91af\">ThreadPool<\/span><span style=\"background:#ffffff;color:#000000\">.QueueUserWorkItem(<\/span><span style=\"background:#ffffff;color:#0000ff\">new<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#2b91af\">WaitCallback<\/span><span style=\"background:#ffffff;color:#000000\">(PushStream), clientCallbackChannel);<\/span><\/li>\n<li style=\"background: #f3f3f3\"><span style=\"background:#ffffff;color:#000000\">}<\/span><\/li>\n<li>&nbsp;<\/li>\n<li style=\"background: #f3f3f3\"><span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">private<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#0000ff\">void<\/span><span style=\"background:#ffffff;color:#000000\"> PushStream(<\/span><span style=\"background:#ffffff;color:#0000ff\">object<\/span><span style=\"background:#ffffff;color:#000000\"> state)<\/span><\/li>\n<li><span style=\"background:#ffffff;color:#000000\">{<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#2b91af\">IClientCallback<\/span><span style=\"background:#ffffff;color:#000000\"> pushCallbackChannel = state <\/span><span style=\"background:#ffffff;color:#0000ff\">as<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#2b91af\">IClientCallback<\/span><span style=\"background:#ffffff;color:#000000\">;<\/span><\/li>\n<li>\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">localStream = <\/span><span style=\"background:#ffffff;color:#0000ff\">new<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#2b91af\">FlowControlledStream<\/span><span style=\"background:#ffffff;color:#000000\">();<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">localStream.ReadThrottle = <\/span><span style=\"background:#ffffff;color:#2b91af\">TimeSpan<\/span><span style=\"background:#ffffff;color:#000000\">.FromMilliseconds(500);<\/span><\/li>\n<li>&nbsp;<\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">pushCallbackChannel.ReceiveStream(localStream);<\/span><\/li>\n<li><span style=\"background:#ffffff;color:#000000\">}<\/span><\/li>\n<li style=\"background: #f3f3f3\">&nbsp;<\/li>\n<li><span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">public<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#0000ff\">void<\/span><span style=\"background:#ffffff;color:#000000\"> StopDownloadingStream()<\/span><\/li>\n<li style=\"background: #f3f3f3\"><span style=\"background:#ffffff;color:#000000\">{<\/span><\/li>\n<li>\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">log.Add(<\/span><span style=\"background:#ffffff;color:#0000ff\">string<\/span><span style=\"background:#ffffff;color:#000000\">.Format(<\/span><span style=\"background:#ffffff;color:#a31515\">&quot;[{0}] StopDownloadingStream Invoked.&quot;<\/span><span style=\"background:#ffffff;color:#000000\">, <\/span><span style=\"background:#ffffff;color:#2b91af\">DateTime<\/span><span style=\"background:#ffffff;color:#000000\">.Now.Minute + <\/span><span style=\"background:#ffffff;color:#a31515\">&quot;:&quot;<\/span><span style=\"background:#ffffff;color:#000000\"> + <\/span><span style=\"background:#ffffff;color:#2b91af\">DateTime<\/span><span style=\"background:#ffffff;color:#000000\">.Now.Second + <\/span><span style=\"background:#ffffff;color:#a31515\">&quot;.&quot;<\/span><span style=\"background:#ffffff;color:#000000\"> + <\/span><span style=\"background:#ffffff;color:#2b91af\">DateTime<\/span><span style=\"background:#ffffff;color:#000000\">.Now.Millisecond));<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#000000\">localStream.StopStreaming = <\/span><span style=\"background:#ffffff;color:#0000ff\">true<\/span><span style=\"background:#ffffff;color:#000000\">;<\/span><\/li>\n<li><span style=\"background:#ffffff;color:#000000\">}<\/span><\/li>\n<\/ol><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<p>With that finished, I need to modify the Web.config that was generated for me. I want to use WebSocket Transport, so I\u2019ll use the standard NetHttpBinding. By default, netHttpBinding will use WebSocket transport if the contract is duplex, so I shouldn\u2019t have to explicitly add that. But I will increase the MaxReceivedMessageSize to a ridiculous value. So, I replaced the generated System.ServiceModel section with the following:<\/p>\n<div id=\"scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:aa1ec992-b4e7-4234-a2db-ee759f2ab73d\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<div style=\"border: #000080 1px solid;color: #000;font-family: 'Courier New', Courier, Monospace;font-size: 10pt\">\n<div style=\"background: #000080;color: #fff;font-family: Verdana, Tahoma, Arial, sans-serif;font-weight: bold;padding: 2px 5px\">Code Snippet<\/div>\n<div style=\"background: #ddd;max-height: 300px;overflow: auto\">\n<ol start=\"1\" style=\"background: #ffffff;margin: 0 0 0 2.5em;padding: 0 0 0 5px\">\n<li><span style=\"background:#ffffff;color:#0000ff\">&lt;<\/span><span style=\"background:#ffffff;color:#a31515\">system.serviceModel<\/span><span style=\"background:#ffffff;color:#0000ff\">&gt;<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0<span style=\"background:#ffffff;color:#0000ff\">&lt;<\/span><span style=\"background:#ffffff;color:#a31515\">behaviors<\/span><span style=\"background:#ffffff;color:#0000ff\">&gt;<\/span><\/li>\n<li>\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#0000ff\">&lt;<\/span><span style=\"background:#ffffff;color:#a31515\">serviceBehaviors<\/span><span style=\"background:#ffffff;color:#0000ff\">&gt;<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#0000ff\">&lt;<\/span><span style=\"background:#ffffff;color:#a31515\">behavior<\/span><span style=\"background:#ffffff;color:#0000ff\"> <\/span><span style=\"background:#ffffff;color:#ff0000\">name<\/span><span style=\"background:#ffffff;color:#0000ff\">=<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\">MyServiceBehavior<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\">&gt;<\/span><\/li>\n<li>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#0000ff\">&lt;<\/span><span style=\"background:#ffffff;color:#a31515\">serviceMetadata<\/span><span style=\"background:#ffffff;color:#0000ff\"> <\/span><span style=\"background:#ffffff;color:#ff0000\">httpGetEnabled<\/span><span style=\"background:#ffffff;color:#0000ff\">=<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\">true<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\"> <\/span><span style=\"background:#ffffff;color:#ff0000\">httpsGetEnabled<\/span><span style=\"background:#ffffff;color:#0000ff\">=<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\">true<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\">\/&gt;<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#0000ff\">&lt;<\/span><span style=\"background:#ffffff;color:#a31515\">serviceDebug<\/span><span style=\"background:#ffffff;color:#0000ff\"> <\/span><span style=\"background:#ffffff;color:#ff0000\">includeExceptionDetailInFaults<\/span><span style=\"background:#ffffff;color:#0000ff\">=<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\">true<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\">\/&gt;<\/span><\/li>\n<li>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#0000ff\">&lt;\/<\/span><span style=\"background:#ffffff;color:#a31515\">behavior<\/span><span style=\"background:#ffffff;color:#0000ff\">&gt;<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#0000ff\">&lt;\/<\/span><span style=\"background:#ffffff;color:#a31515\">serviceBehaviors<\/span><span style=\"background:#ffffff;color:#0000ff\">&gt;<\/span><\/li>\n<li>\u00a0\u00a0<span style=\"background:#ffffff;color:#0000ff\">&lt;\/<\/span><span style=\"background:#ffffff;color:#a31515\">behaviors<\/span><span style=\"background:#ffffff;color:#0000ff\">&gt;<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0<span style=\"background:#ffffff;color:#0000ff\">&lt;<\/span><span style=\"background:#ffffff;color:#a31515\">serviceHostingEnvironment<\/span><span style=\"background:#ffffff;color:#0000ff\"> <\/span><span style=\"background:#ffffff;color:#ff0000\">aspNetCompatibilityEnabled<\/span><span style=\"background:#ffffff;color:#0000ff\">=<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\">true<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\"> <\/span><span style=\"background:#ffffff;color:#ff0000\">multipleSiteBindingsEnabled<\/span><span style=\"background:#ffffff;color:#0000ff\">=<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\">true<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\"> \/&gt;<\/span><\/li>\n<li>\u00a0\u00a0<span style=\"background:#ffffff;color:#0000ff\">&lt;<\/span><span style=\"background:#ffffff;color:#a31515\">bindings<\/span><span style=\"background:#ffffff;color:#0000ff\">&gt;<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#0000ff\">&lt;<\/span><span style=\"background:#ffffff;color:#a31515\">netHttpBinding<\/span><span style=\"background:#ffffff;color:#0000ff\">&gt;<\/span><\/li>\n<li>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#0000ff\">&lt;<\/span><span style=\"background:#ffffff;color:#a31515\">binding<\/span><span style=\"background:#ffffff;color:#0000ff\"> <\/span><span style=\"background:#ffffff;color:#ff0000\">name<\/span><span style=\"background:#ffffff;color:#0000ff\">=<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\">MyBinding<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\"> <\/span><span style=\"background:#ffffff;color:#ff0000\">maxReceivedMessageSize<\/span><span style=\"background:#ffffff;color:#0000ff\">=<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\">67108864<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\"> <\/span><span style=\"background:#ffffff;color:#ff0000\">transferMode<\/span><span style=\"background:#ffffff;color:#0000ff\">=<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\">Streamed<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\">&gt;<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#0000ff\">&lt;\/<\/span><span style=\"background:#ffffff;color:#a31515\">binding<\/span><span style=\"background:#ffffff;color:#0000ff\">&gt;<\/span><\/li>\n<li>\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#0000ff\">&lt;\/<\/span><span style=\"background:#ffffff;color:#a31515\">netHttpBinding<\/span><span style=\"background:#ffffff;color:#0000ff\">&gt;<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0<span style=\"background:#ffffff;color:#0000ff\">&lt;\/<\/span><span style=\"background:#ffffff;color:#a31515\">bindings<\/span><span style=\"background:#ffffff;color:#0000ff\">&gt;<\/span><\/li>\n<li>\u00a0\u00a0<span style=\"background:#ffffff;color:#0000ff\">&lt;<\/span><span style=\"background:#ffffff;color:#a31515\">services<\/span><span style=\"background:#ffffff;color:#0000ff\">&gt;<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#0000ff\">&lt;<\/span><span style=\"background:#ffffff;color:#a31515\">service<\/span><span style=\"background:#ffffff;color:#0000ff\"> <\/span><span style=\"background:#ffffff;color:#ff0000\">behaviorConfiguration<\/span><span style=\"background:#ffffff;color:#0000ff\">=<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\">MyServiceBehavior<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\"> <\/span><span style=\"background:#ffffff;color:#ff0000\">name<\/span><span style=\"background:#ffffff;color:#0000ff\">=<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\">DuplexService.StreamingService<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\">&gt;<\/span><\/li>\n<li>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#0000ff\">&lt;<\/span><span style=\"background:#ffffff;color:#a31515\">endpoint<\/span><span style=\"background:#ffffff;color:#0000ff\"> <\/span><span style=\"background:#ffffff;color:#ff0000\">address<\/span><span style=\"background:#ffffff;color:#0000ff\">=<\/span><span style=\"background:#ffffff;color:#000000\">&quot;&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\"> <\/span><span style=\"background:#ffffff;color:#ff0000\">contract<\/span><span style=\"background:#ffffff;color:#0000ff\">=<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\">CommonArtifacts.IStreamService<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\"> <\/span><span style=\"background:#ffffff;color:#ff0000\">binding<\/span><span style=\"background:#ffffff;color:#0000ff\">=<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\">netHttpBinding<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\"> <\/span><span style=\"background:#ffffff;color:#ff0000\">bindingConfiguration<\/span><span style=\"background:#ffffff;color:#0000ff\">=<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\">MyBinding<\/span><span style=\"background:#ffffff;color:#000000\">&quot;<\/span><span style=\"background:#ffffff;color:#0000ff\"> \/&gt;<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0\u00a0\u00a0\u00a0<span style=\"background:#ffffff;color:#0000ff\">&lt;\/<\/span><span style=\"background:#ffffff;color:#a31515\">service<\/span><span style=\"background:#ffffff;color:#0000ff\">&gt;<\/span><\/li>\n<li>\u00a0\u00a0<span style=\"background:#ffffff;color:#0000ff\">&lt;\/<\/span><span style=\"background:#ffffff;color:#a31515\">services<\/span><span style=\"background:#ffffff;color:#0000ff\">&gt;<\/span><\/li>\n<li style=\"background: #f3f3f3\"><span style=\"background:#ffffff;color:#0000ff\">&lt;\/<\/span><span style=\"background:#ffffff;color:#a31515\">system.serviceModel<\/span><span style=\"background:#ffffff;color:#0000ff\">&gt;<\/span><\/li>\n<\/ol><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<p>So, after that, I open the service\u2019s Properties page, go to the Web section, and make sure \u201cUse Local IIS Web server\u201d is selected, and I uncheck \u201cUse IIS Express\u201d. When I save that, and allow VS to create the virtual directory, I can browse to the .svc file and get the standard WCF Service help page. Time to work on the Client code.<\/p>\n<p>The goal for the client is to prove that we are doing true bi-directional streaming. To do this my client will execute the following:<\/p>\n<p>1. Invoke a service operation to start downloading a stream.<\/p>\n<p>2. Signal that bytes are being received.<\/p>\n<p>3. Upload a stream for a few seconds.<\/p>\n<p>4. Signal to the service to stop sending bytes to the receiver.<\/p>\n<p>5. Wait for the end of the stream.<\/p>\n<p>If the service can\u2019t process the incoming stream while sending bytes out, then it will deadlock. The program is in the attached zip file, but here\u2019s a snipped version:<\/p>\n<div id=\"scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:cd75c940-da0a-4037-9f93-3c2530353751\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<div style=\"border: #000080 1px solid;color: #000;font-family: 'Courier New', Courier, Monospace;font-size: 10pt\">\n<div style=\"background: #000080;color: #fff;font-family: Verdana, Tahoma, Arial, sans-serif;font-weight: bold;padding: 2px 5px\">Code Snippet<\/div>\n<div style=\"background: #ddd;max-height: 300px;overflow: auto\">\n<ol start=\"1\" style=\"background: #ffffff;margin: 0 0 0 2em;padding: 0 0 0 5px\">\n<li><span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#2b91af\">ClientReceiver<\/span><span style=\"background:#ffffff;color:#000000\"> receiver = <\/span><span style=\"background:#ffffff;color:#0000ff\">new<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#2b91af\">ClientReceiver<\/span><span style=\"background:#ffffff;color:#000000\">();<\/span><\/li>\n<li style=\"background: #f3f3f3\">&nbsp;<\/li>\n<li><span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#0000ff\">string<\/span><span style=\"background:#ffffff;color:#000000\"> address = <\/span><span style=\"background:#ffffff;color:#a31515\">&quot;http:\/\/localhost\/DuplexService\/DuplexService.svc&quot;<\/span><span style=\"background:#ffffff;color:#000000\">;<\/span><\/li>\n<li style=\"background: #f3f3f3\"><span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#2b91af\">NetHttpBinding<\/span><span style=\"background:#ffffff;color:#000000\"> binding = <\/span><span style=\"background:#ffffff;color:#0000ff\">new<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#2b91af\">NetHttpBinding<\/span><span style=\"background:#ffffff;color:#000000\">();<\/span><\/li>\n<li><span style=\"background:#ffffff;color:#000000\">binding.MaxReceivedMessageSize = 64 * 1024 * 1024;<\/span><\/li>\n<li style=\"background: #f3f3f3\"><span style=\"background:#ffffff;color:#000000\">binding.TransferMode = <\/span><span style=\"background:#ffffff;color:#2b91af\">TransferMode<\/span><span style=\"background:#ffffff;color:#000000\">.Streamed;<\/span><\/li>\n<li><span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#2b91af\">DuplexChannelFactory<\/span><span style=\"background:#ffffff;color:#000000\">&lt;<\/span><span style=\"background:#ffffff;color:#2b91af\">IStreamService<\/span><span style=\"background:#ffffff;color:#000000\">&gt; factory = <\/span><span style=\"background:#ffffff;color:#0000ff\">new<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#2b91af\">DuplexChannelFactory<\/span><span style=\"background:#ffffff;color:#000000\">&lt;<\/span><span style=\"background:#ffffff;color:#2b91af\">IStreamService<\/span><span style=\"background:#ffffff;color:#000000\">&gt;(<\/span><span style=\"background:#ffffff;color:#0000ff\">new<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#2b91af\">InstanceContext<\/span><span style=\"background:#ffffff;color:#000000\">(receiver), binding, address);<\/span><\/li>\n<li style=\"background: #f3f3f3\"><span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#2b91af\">IStreamService<\/span><span style=\"background:#ffffff;color:#000000\"> client = factory.CreateChannel();<\/span><\/li>\n<\/ol><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<div id=\"scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:57cda9a0-9584-418e-8efc-abf7fa500e35\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<div style=\"border: #000080 1px solid;color: #000;font-family: 'Courier New', Courier, Monospace;font-size: 10pt\">\n<div style=\"background: #000080;color: #fff;font-family: Verdana, Tahoma, Arial, sans-serif;font-weight: bold;padding: 2px 5px\">Code Snippet<\/div>\n<div style=\"background: #ddd;max-height: 300px;overflow: auto\">\n<ol start=\"1\" style=\"background: #ffffff;margin: 0 0 0 2.5em;padding: 0 0 0 5px\">\n<li><span style=\"background:#ffffff;color:#000000\">client.StartDownloadingStream();<\/span><\/li>\n<li style=\"background: #f3f3f3\">&nbsp;<\/li>\n<li>\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#2b91af\">Console<\/span><span style=\"background:#ffffff;color:#000000\">.WriteLine(<\/span><span style=\"background:#ffffff;color:#a31515\">&quot;[{0}] Waiting for the receiver to start reading bytes.&quot;<\/span><span style=\"background:#ffffff;color:#000000\">, <\/span><span style=\"background:#ffffff;color:#2b91af\">DateTime<\/span><span style=\"background:#ffffff;color:#000000\">.Now.Minute + <\/span><span style=\"background:#ffffff;color:#a31515\">&quot;:&quot;<\/span><span style=\"background:#ffffff;color:#000000\"> + <\/span><span style=\"background:#ffffff;color:#2b91af\">DateTime<\/span><span style=\"background:#ffffff;color:#000000\">.Now.Second + <\/span><span style=\"background:#ffffff;color:#a31515\">&quot;.&quot;<\/span><span style=\"background:#ffffff;color:#000000\"> + <\/span><span style=\"background:#ffffff;color:#2b91af\">DateTime<\/span><span style=\"background:#ffffff;color:#000000\">.Now.Millisecond);<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0<span style=\"background:#ffffff;color:#000000\">receiver.ReceiveStreamInvoked.WaitOne();<\/span><\/li>\n<li>&nbsp;<\/li>\n<li style=\"background: #f3f3f3\">\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#2b91af\">Console<\/span><span style=\"background:#ffffff;color:#000000\">.WriteLine(<\/span><span style=\"background:#ffffff;color:#a31515\">&quot;[{0}] Client Invoking UploadStream, while the receiver is receiving bytes.&quot;<\/span><span style=\"background:#ffffff;color:#000000\">, <\/span><span style=\"background:#ffffff;color:#2b91af\">DateTime<\/span><span style=\"background:#ffffff;color:#000000\">.Now.Minute + <\/span><span style=\"background:#ffffff;color:#a31515\">&quot;:&quot;<\/span><span style=\"background:#ffffff;color:#000000\"> + <\/span><span style=\"background:#ffffff;color:#2b91af\">DateTime<\/span><span style=\"background:#ffffff;color:#000000\">.Now.Second + <\/span><span style=\"background:#ffffff;color:#a31515\">&quot;.&quot;<\/span><span style=\"background:#ffffff;color:#000000\"> + <\/span><span style=\"background:#ffffff;color:#2b91af\">DateTime<\/span><span style=\"background:#ffffff;color:#000000\">.Now.Millisecond);<\/span><\/li>\n<li>\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#2b91af\">FlowControlledStream<\/span><span style=\"background:#ffffff;color:#000000\"> uploadStream = <\/span><span style=\"background:#ffffff;color:#0000ff\">new<\/span><span style=\"background:#ffffff;color:#000000\"> <\/span><span style=\"background:#ffffff;color:#2b91af\">FlowControlledStream<\/span><span style=\"background:#ffffff;color:#000000\">();<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0<span style=\"background:#ffffff;color:#000000\">uploadStream.ReadThrottle = <\/span><span style=\"background:#ffffff;color:#2b91af\">TimeSpan<\/span><span style=\"background:#ffffff;color:#000000\">.FromMilliseconds(500);<\/span><\/li>\n<li>\u00a0<span style=\"background:#ffffff;color:#000000\">uploadStream.StreamDuration = <\/span><span style=\"background:#ffffff;color:#2b91af\">TimeSpan<\/span><span style=\"background:#ffffff;color:#000000\">.FromSeconds(5);<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0<span style=\"background:#ffffff;color:#000000\">client.UploadStream(uploadStream);<\/span><\/li>\n<li>&nbsp;<\/li>\n<li style=\"background: #f3f3f3\">\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#2b91af\">Console<\/span><span style=\"background:#ffffff;color:#000000\">.WriteLine(<\/span><span style=\"background:#ffffff;color:#a31515\">&quot;[{0}] Client Invoking StopDownloadingStream.&quot;<\/span><span style=\"background:#ffffff;color:#000000\">, <\/span><span style=\"background:#ffffff;color:#2b91af\">DateTime<\/span><span style=\"background:#ffffff;color:#000000\">.Now.Minute + <\/span><span style=\"background:#ffffff;color:#a31515\">&quot;:&quot;<\/span><span style=\"background:#ffffff;color:#000000\"> + <\/span><span style=\"background:#ffffff;color:#2b91af\">DateTime<\/span><span style=\"background:#ffffff;color:#000000\">.Now.Second + <\/span><span style=\"background:#ffffff;color:#a31515\">&quot;.&quot;<\/span><span style=\"background:#ffffff;color:#000000\"> + <\/span><span style=\"background:#ffffff;color:#2b91af\">DateTime<\/span><span style=\"background:#ffffff;color:#000000\">.Now.Millisecond);<\/span><\/li>\n<li>\u00a0<span style=\"background:#ffffff;color:#000000\">client.StopDownloadingStream();<\/span><\/li>\n<li style=\"background: #f3f3f3\">&nbsp;<\/li>\n<li>\u00a0<span style=\"background:#ffffff;color:#000000\"><\/span><span style=\"background:#ffffff;color:#2b91af\">Console<\/span><span style=\"background:#ffffff;color:#000000\">.WriteLine(<\/span><span style=\"background:#ffffff;color:#a31515\">&quot;[{0}] Waiting on ReceiveStreamCompleted from the receiver.&quot;<\/span><span style=\"background:#ffffff;color:#000000\">, <\/span><span style=\"background:#ffffff;color:#2b91af\">DateTime<\/span><span style=\"background:#ffffff;color:#000000\">.Now.Minute + <\/span><span style=\"background:#ffffff;color:#a31515\">&quot;:&quot;<\/span><span style=\"background:#ffffff;color:#000000\"> + <\/span><span style=\"background:#ffffff;color:#2b91af\">DateTime<\/span><span style=\"background:#ffffff;color:#000000\">.Now.Second + <\/span><span style=\"background:#ffffff;color:#a31515\">&quot;.&quot;<\/span><span style=\"background:#ffffff;color:#000000\"> + <\/span><span style=\"background:#ffffff;color:#2b91af\">DateTime<\/span><span style=\"background:#ffffff;color:#000000\">.Now.Millisecond);<\/span><\/li>\n<li style=\"background: #f3f3f3\">\u00a0<span style=\"background:#ffffff;color:#000000\">receiver.ReceiveStreamCompleted.WaitOne();<\/span><\/li>\n<\/ol><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<p>Running it produces the following log:<\/p>\n<blockquote>\n<p><font face=\"Courier New\">[45:21.308] Client Invoking StartDownloadingStream.<\/font><\/p>\n<p><font face=\"Courier New\">[45:21.844] Waiting for the receiver to start reading bytes.<\/font><\/p>\n<p><font face=\"Courier New\">[45:22.861] ReceiveStream invoked.<\/font><\/p>\n<p><font face=\"Courier New\">[45:22.862] Client Invoking UploadStream, while the receiver is receiving bytes.<\/font><\/p>\n<p><font face=\"Courier New\">[45:27.873] Client Invoking StopDownloadingStream.<\/font><\/p>\n<p><font face=\"Courier New\">[45:27.873] Waiting on ReceiveStreamCompleted from the receiver.<\/font><\/p>\n<p><font face=\"Courier New\">[45:28.371] ReceiveStream read 725248 bytes.<\/font><\/p>\n<p><font face=\"Courier New\">[45:28.371] Getting the log from the server.<\/font><\/p>\n<p><font face=\"Courier New\">The following are the logs from the server:<\/font><\/p>\n<p><font face=\"Courier New\">[45:21.854] StartDownloadingStream Invoked.<\/font><\/p>\n<p><font face=\"Courier New\">[45:23.866] UploadStream Invoked.<\/font><\/p>\n<p><font face=\"Courier New\">[45:27.873] UploadStream Read 528640 bytes.<\/font><\/p>\n<p><font face=\"Courier New\">[45:27.874] StopDownloadingStream Invoked.<\/font><\/p>\n<p><font face=\"Courier New\">[45:28.373] DownloadLog Invoked.<\/font><\/p>\n<\/blockquote>\n<p>Comparing the server log and the client log shows that server read bytes from the client for about 5 seconds while sending bytes to the client at the same time. I made sure to set the ReadThrottle to the same amount on both client and service, so the client <i>should<\/i> read more bytes than the service, which it does.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>DuplexBiDirectionalStreaming VS2012 project DuplexBiDirectionalStreaming.zip Introduction With WebSocket transport, it\u2019s possible to use streamed transport on the Duplex Callback \u2013 something that was previously a technical limitation with WCF but is now possible using this transport. New to .Net4.5 is the NetHttpBinding (and NetHttpsBinding), which is a new standard binding that leverages the WebSocket transport if [&hellip;]<\/p>\n","protected":false},"author":457,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[197],"tags":[],"class_list":["post-2154","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-aspnet"],"acf":[],"blog_post_summary":"<p>DuplexBiDirectionalStreaming VS2012 project DuplexBiDirectionalStreaming.zip Introduction With WebSocket transport, it\u2019s possible to use streamed transport on the Duplex Callback \u2013 something that was previously a technical limitation with WCF but is now possible using this transport. New to .Net4.5 is the NetHttpBinding (and NetHttpsBinding), which is a new standard binding that leverages the WebSocket transport if [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/2154","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/457"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=2154"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/2154\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=2154"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=2154"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=2154"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}