Fixing “Unable to read data from the transport connection” error when transferring data to web service from WinMo via Orange UK

This post doesn’t have a particularly catchy title and a might be tiny bit dull for non-techies, but I just wanted to share a problem and solution that cost me many hours to diagnose and resolve. Hopefully this will help somebody experiencing the same problem in the future.

Let’s start from the beginning:

Assumptions

  • You’re writing an application which uses a handheld device to send a large byte array to a web method within a web service.
     
  • Your solution works perfectly over a standard WiFi connection and on most mobile networks, however you have started to receive intermittent errors on some carriers (Orange UK)? It seems as if the network is prematurely terminating streams of large data.

    System.Net.WebException: Unable to read data from the transport connection – read stack trace

  • You’ve tried everything you can think of and don’t want to split it up as you’re using compression and it’s a nice elegant solution.
     
  • You’re about to give up and exclude users from an entire mobile network from using your solution 🙂

StackTrace at System.Net.HttpWebRequest.finishGetResponse()
at System.Net.HttpWebRequest.GetResponse()
at System.Web.Services.Protocols.WebClientProtocol.GetWebResponse()
at System.Web.Services.Protocols.HttpWebClientProtocol.GetWebResponse()
at System.Web.Services.Protocols.SoapHttpClientProtocol.doInvoke()
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke()

STOP

The Problem

Using a packet tracer like Smart Sniff, I was able to trace TCP/IP packets through the Windows Mobile Remote Adapter interface and noticed a strange looking HTTP request which looked something like this:
 

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema xmlns="http://x"><cpIn>..........................................................................................................
..............................................................................................................................................................................................................
..............................................................................................................................................................................................................
..............................................................................................................................................................................................................
..............................................................................................................................................................................................................
..............................................................................................................................................................................................................
....................................................................

In the example above, these dots are all zeros in hex, but what was being sent by the handheld during tests was an actual compressed byte array, so the correct data was being passed from the client to the web service.

So what’s wrong?

The MTU, or Maximum Transmission Unit, of a device is a parameter which defines the size of packets which can be sent over a particular network.

Whether connecting via ActiveSync via a PC, using WiFi or via the mobile network, the maximum size of packets that can be sent is determined by the MTU.

Some mobile networks, like Orange in the UK, have slightly different MTU values. So if the device tries to send a packet with a size LARGER than the network’s MTU, it seems to clear them and set them all to zero. Every packet that was sent to the network during the test whose packet size is under the network’s MTU was delivered successfully.

So what can I do to work around this?

The best solution is to provide the user with the option to set the MTU for the device you’re working with to a value LOWER than the network’s MTU.

The MTU value is stored in the Windows Mobile registry and is located in the registry path:
 

HKEY_LOCAL_MACHINECommTcpipParms

I set the MTU for Orange to 1300, which appeared to resolve the problem.

Once you’ve set this, make sure you tell TCP to use a fixed MTU as specified by setting EnablePMTUDiscovery to true in the same registry path. This determines whether TCP uses a fixed, default maximum transmission unit (MTU) or attempts to detect the actual MTU.

Here’s a basic C# class I created to allow the user to perform this action on the mobile. If you have problems with application signing, use a test certificate.

using System.Runtime.InteropServices;

namespace Cap.SharedServices
{
    public partial class MTUFix
    {

        [DllImport("aygshell.dll")]
        private static extern bool ExitWindowsEx(int uFlags, int dwReserved);

        private const int EWX_REBOOT = 2;

        public MTUFix()
        {

            InitializeComponent();

            Cursor.Current = Cursors.Default;

        }
        private void setMTU(object sender, EventArgs e)
        {
            RegistryKey reg = Registry.LocalMachine;

            reg = reg.OpenSubKey("CommTcpipParms", true);

            reg.SetValue("MTU", 1300);

            reg.SetValue("EnablePMTUDiscovery", 0);

            reg.Close();

            MessageBox.Show("Changes applied to registry successfully.rnrnThe application will now exit and you must now restart.rnrnPress OK to continue...");

            ExitWindowsEx(EWX_REBOOT, 0);
        }
    }
}  

If it doesn’t work for you, play around with the MTU or contact your carrier for the exact MTU for the network.
 

Reboot your device (soft) and your problem should be resolved.

Leave a Reply