Answered Sending a large file using streamed transfer mode fails

  • Friday, April 27, 2012 2:26 PM
     
      Has Code

    Hi Everyone,

    This is my first post here in MSDN forum. I am already a ASP.NET forum member, but my problem is not appropriate for that forum. So, I ended up here.

    I followed correctly the codes and configurations of implementing streaming transfer using BasicHttpBinding from different forum sites. My windows application is working in sending small size file to a remote host where the web service is self-hosted, but it is not working in sending large size file. The error message is not very helpful.

    The following is the exception message (ex.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 '00:59:57.3750000'."

    And the inner exception message (ex.InnerException.Message):

    "Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host."

    And the inner exception message (ex.InnerException.InnerException.Message):

    "An existing connection was forcibly closed by the remote host"

    I tried to catch the error inside the service implementation method, but the program flow did not even go inside. I think the problem is in the application configuration. Correct me if I am wrong.

    The following code is from the application configuration file (app.config):

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
    	<system.serviceModel>
    		<services>
    			<service behaviorConfiguration="WcfStreamTransmission.StreamTransmissionServiceBehavior"
    					 name="WcfStreamTransmission.StreamTransmissionService">
    				<host>
    					<baseAddresses>
    						<add baseAddress="http://localhost:9000/StreamTransmissionService.svc" />
    					</baseAddresses>
    				</host>
    				<endpoint address=""
    						  binding="basicHttpBinding"
    						  contract="WcfStreamTransmission.IStreamTransmissionService" />
    				<endpoint address="mex"
    						  binding="mexHttpBinding"
    						  contract="IMetadataExchange" />
    			</service>
    		</services>
    		<bindings>
    			<basicHttpBinding>
    				<binding name="BasicHttpBinding_IStreamTransmissionService"
    						 maxReceivedMessageSize="2147483647"
    						 receiveTimeout="00:10:00"
    						 sendTimeout="01:00:00"
    						 transferMode="Streamed">
    				</binding>
    			</basicHttpBinding>
    		</bindings>
    		<client>
    			<endpoint address="http://webservice.domain.com:9000/StreamTransmissionService.svc"
    					  binding="basicHttpBinding"
    					  bindingConfiguration="BasicHttpBinding_IStreamTransmissionService"
    					  contract="WcfStreamTransmission.IStreamTransmissionService"
    					  name="BasicHttpBinding_IStreamTransmissionService" />
    		</client>
    		<behaviors>
    			<serviceBehaviors>
    				<behavior name="WcfStreamTransmission.StreamTransmissionServiceBehavior">
    					<serviceMetadata httpGetEnabled="true" />
    					<serviceDebug includeExceptionDetailInFaults="true" />
    					<serviceThrottling maxConcurrentCalls="2147483647"
    									   maxConcurrentInstances="2147483647"
    									   maxConcurrentSessions="2147483647" />
    					<dataContractSerializer maxItemsInObjectGraph="2147483647" />
    				</behavior>
    			</serviceBehaviors>
    		</behaviors>
    	</system.serviceModel>
    </configuration>

    The domain webservice.domain.com is not the real host. Notice that the sendTimeout affects the socket local timeout that the error is saying. Even if I set it to 1 hour, the error is still appearing. I set the transferMode to Streamed and the maxReceivedMessageSize to Int32.MaxValue so that it can accept large file. I also set the serviceThrottling attributes and all the integer attributes to Int32.MaxValue, but the error is still appearing. What is the correct configuration? It has been more than two weeks, but I still cannot find the right solution.


    The following is the message contract to be sent:

    using System.IO;
    using System.Net.Security;
    using System.ServiceModel;
    
    namespace WcfStreamTransmission
    {
        [MessageContract]
        public class FileStreamMessage
        {
            [MessageHeader(MustUnderstand = true, ProtectionLevel = ProtectionLevel.None)]
            public string Name { get; set; }
    
            [MessageBodyMember(Order = 1, ProtectionLevel = ProtectionLevel.None)]
            public Stream Data { get; set; }
        }
    }


    The following is the service contract:

    using System.IO;
    using System.ServiceModel;
    
    namespace WcfStreamTransmission
    {
        [ServiceContract]
        public interface IStreamTransmissionService
        {
            [OperationContract]
            void Upload(FileStreamMessage message);
        }
    }

    Do I miss something?

    Your immediate response is highly appreciated.

    Thank you.



    • Edited by autobyte Friday, April 27, 2012 2:41 PM I explain the webservice.domain.com
    • Edited by autobyte Friday, April 27, 2012 3:21 PM I explain the application configuration
    •  

All Replies

  • Saturday, April 28, 2012 1:22 AM
     
     

    Hi, You don't seem to have have a bindingConfiguration set on the service endpoint. You do have it set on the client endpoint though.

    Also, is this a mix of your service and client or do they originally belong in different config files?

    I would expect the client config file to contain the <client> config element only and the service config to contain the <service> config element only

  • Saturday, April 28, 2012 8:23 AM
     
     

    Hi rupex,

    Yes, it is the combination of client and service in a single application.

    The following image is the form after starting the application and before starting the service host:

    before starting the service

    If you want to start the service host, click the Start button. When the Start button is clicked, the Browse button for selecting the folder will be disabled and the service host will start immediately.

    The following image is the form after starting the service host:

    after starting the service host

    The application is now ready to receive file from the same application in a remote machine.

    My simple file transfer application is the like the function of sending a file in Yahoo Messenger. The client is also the service.

    It can send small file, but not the large file. What is behind this problem?

  • Saturday, April 28, 2012 10:46 AM
     
      Has Code

    As I pointed out, you need to set the bindingConfiguration on the service as well as the client.

    Change Service Endpoint:

    <endpoint address="" binding="basicHttpBinding" contract="WcfStreamTransmission.IStreamTransmissionService" />

    To this:

    <endpoint address="" binding="basicHttpBinding" contract="WcfStreamTransmission.IStreamTransmissionService" bindingConfiguration="BasicHttpBinding_IStreamTransmissionService"/>

  • Monday, April 30, 2012 1:44 AM
     
     

    Hi Rupex,

    Thank you for your immediate reply.

    The error still appears. Is there any other way?

    If you want to have the full source projects of this, you can download it from my skydrive. Here is my project WcfSimpleFileTransfer. Just change the address webservice.domain.com:9000 in the application configuration file into your real remote host path and don't forget to add the port (like 9000 in my project) to your remote host firewall.

    Just let me know if I have missing something. Thanks.

    • Edited by autobyte Monday, April 30, 2012 5:36 AM add the full source code
    •  
  • Monday, April 30, 2012 7:07 AM
    Moderator
     
      Has Code

    Try increasing the value of maxRequestLength and executionTimeout attributes in the <httpRuntime> element in the config file, something as follows.

    <configuration>
       <system.web>
          <httpRuntime maxRequestLength="1048576"
             executionTimeout="3600" />
       </system.web>
    </configuration>

    But I downloaded your sample and applied it on my computer, I have found some doubts while runing your project:

    1.In the App.config file, the baseAddress contains 'StreamTransmissionService.svc', but I see the WcfStreamTransmission project, it did not contains StreamTransmissionService.svc file.

    2.Did you want to wrap starting WCF service and transferring file from the client side in one application? or could I understand it as follows?

    In one computer we need to start WCF service by using the frmMessenger form and in another computer we also need to run this frmMessenger form and choose one file to transfer.


    Please mark the replies as answers if they help or unmark if not. If you have any feedback about my replies, please contact msdnmg@microsoft.com Microsoft One Code Framework

  • Monday, April 30, 2012 8:32 AM
     
     

    Hi Peter,

    I try to add that configuration, but there is an error.

    The following is the exception message (ex.Message):

    "The type initializer for 'System.ServiceModel.ClientBase`1' threw an exception."

    And the inner exception message (ex.InnerException.Message):

    "The type initializer for 'System.ServiceModel.DiagnosticUtility' threw an exception."

    And the inner exception message (ex.InnerException.InnerException.Message):

    "Configuration system failed to initialize"

    And the inner exception message (ex.InnerException.InnerException.InnerException.Message):

    "Unrecognized configuration section configuration. (D:\\WcfSimpleFileTransfer\\WcfSimpleFileTransfer\\bin\\Debug\\WcfSimpleFileTransfer.vshost.exe.config line 8)"

    I think that configuration is not recognized. I heard that httpRuntime is only applicable for IIS-hosted WCF service, but my service is self-hosted.

    About your question 1:

    I didn't notice that. But I think it is not a big deal, because it runs with or without .svc, as long as the address path of service endpoint and client endpoint are the same. That is just for naming purpose. I also heard that .svc file is only used by the IIS to locate the service to be hosted. Correct me if I am wrong.

    About your question 2:

    Yes, what you think is right. You must run a frmMessenger form in a computer and start hosting to listen to incoming service call, and also run a frmMessenger form in another computer and choose a file to transfer.

    Thanks.

    • Edited by autobyte Monday, April 30, 2012 1:17 PM
    • Edited by autobyte Wednesday, May 02, 2012 1:45 AM
    • Edited by autobyte Wednesday, May 02, 2012 1:46 AM
    • Edited by autobyte Wednesday, May 02, 2012 1:47 AM
    • Edited by autobyte Wednesday, May 02, 2012 1:56 AM
    • Edited by autobyte Wednesday, May 02, 2012 1:57 AM
    •  
  • Wednesday, May 02, 2012 2:20 AM
     
     

    Hi to all,

    Kindly help me to debug my simple file transfer project. I am near the solution. I think my only problem is the application configuration. Kindly download the project from here.

    Thank you.

  • Wednesday, May 02, 2012 5:41 AM
    Moderator
     
     
    I have runned your sample project on my computer, in your project, I changed the base address 'localhost:9000' to the 'IP:9000' (e.g: '157.60.60.162:9000', this IP is IPv4 address) and  webservice.domain.com:9000 also changed to '157.60.60.162:9000' in the application configuration file, and in the Windows Firewall I specify spcified port 9000. but when I started WCF service in one computer and started client application in another computer, I can send large file to the server (So far I can send a file with 15.4MB ), so I want to know what is the size of the large file you sent to the server that it will throw the above exception?

    Please mark the replies as answers if they help or unmark if not. If you have any feedback about my replies, please contact msdnmg@microsoft.com Microsoft One Code Framework

  • Wednesday, May 02, 2012 10:49 AM
     
     

    Hi Peter,

    Really?! We do the same thing, and the size of the file that I want to be sent is only 120 KB (123,392 bytes). Is it a network problem? Have you tried to run my application in separate computers outside the domain or local area network? For example, the server is in www.google.com (74.125.71.100), and the client is in www.yahoo.com (209.191.122.70). I wonder why.

    Thanks.

  • Thursday, May 03, 2012 3:27 AM
    Moderator
     
     Answered
    Yes, I only change the address of WCF service and specify specified port 9000 in window firewall. I run the client and server in different computers in my local area connection, and then I can send file with 15.4MB. First you need to make sure that you can ping to another computer, it is maybe network or proxy server issues.

    Please mark the replies as answers if they help or unmark if not. If you have any feedback about my replies, please contact msdnmg@microsoft.com Microsoft One Code Framework

    • Marked As Answer by autobyte Friday, May 04, 2012 12:27 PM
    •  
  • Thursday, May 03, 2012 3:48 AM
     
     
    Yes, I can ping to another computer because I can send although small file only. And the host address is not restricted in our proxy server. Have you tried to run my application and send file over the internet? I think it is some issue that is not clearly explained by the error message.
  • Friday, May 04, 2012 8:14 AM
    Moderator
     
     
    When I run this application on across domain computers separately, I have changed the WCF service address to www.google.com (74.125.71.100), and at this moment, when I sent that file to the server, it throwed an error that indicates timeout.

    Please mark the replies as answers if they help or unmark if not. If you have any feedback about my replies, please contact msdnmg@microsoft.com Microsoft One Code Framework

  • Friday, May 04, 2012 8:33 AM
     
      Has Code

    Could you please change the binding settings to the following 

    <binding name="BasicHttpBinding_IStreamTransmissionService" maxReceivedMessageSize="2147483647" receiveTimeout="02:10:00" sendTimeout="02:00:00"

    OpenTimeout="02:00:00"

    CloseTimeout="02:00:00"

    maxbuffersize="2147483647" maxbufferpoolsize="2147483647"

    transferMode="Streamed"> </binding>

    also set the readerquotas in binding 

    <readerQuotas maxArrayLength="Integer" maxBytesPerRead="Integer" maxDepth="Integer" maxNameTableCharCount="Integer" maxStringContentLength=="Integer" />

    It is worth enable tracing in your service. It will lead you to more appropriate error.


    Tanvir Huda Application Architect/Consultant http://thetechnocrate.wordpress.com/

  • Friday, May 04, 2012 12:19 PM
     
     Answered

    Hi Everyone,

    Finally, I got the answer. My code has no problem. It is a network issue.

    Our proxy server Squid forcibly closes the connection when the file is large. The remote host address and the port 9000 are not allowed to send outgoing data in the network firewall and the proxy server. I noticed it when I connect my network cable directly to the modem, it sends successfully, but if I connect it back to our local area network, it doesn't.

    I ask our network admin to assist me. Now, I can finally send large file.

    If you want test my program even if the proxy server is on, you have to ask first your network admin to configure the proxy server and network firewall if enabled. Then, you can follow these instructions:

    1. Open your Internet Explorer
    2. At the Tools menu, click the Internet Options menu
    3. When the Internet Options dialog appears, click the Connections tab
    4. At the Connections tab, click the LAN settings button
    5. When the Local Area Network (LAN) Settings dialog appears, check to use a proxy server for your LAN and click the Advanced button (see Figure 1)
    6. When the Proxy Settings dialog appears, append the domain name or the IP address to the exceptions (see Figure 2)
    7. And click OK button, and OK button, and OK button

    If the proxy settings of your browser is enabled and the proxy server is on, you can use the internet in your browser while running the program.

    Figure 1:

    LAN Settings

    Figure 2:

    Proxy Settings

    You can download my clean code here.

    I will try to send different kind of file. If there is exception, I will post it immediately. You can try also, and kindly post the error here. So far, my only goal is to send XML file to any location, and I have no problem sending it.

    Thank you Peter, rupex, and Tanvir. You are all genius men. God bless you.


    • Edited by autobyte Friday, May 04, 2012 12:23 PM add images
    • Marked As Answer by autobyte Friday, May 04, 2012 12:27 PM
    •  
  • Monday, May 07, 2012 6:42 PM
     
     
    You can do it!