Using EndOfStream causes hanging - RFCOMM streams

Topics: Bluetooth - Microsoft
Jan 8, 2014 at 3:29 PM
Hello all,


I am trying to transfer some data of data through RFCOMM using streams. I send data out, and it gets echoed back.
BluetoothClient bc = new BluetoothClient();
            BluetoothDeviceInfo[] devices = bc.DiscoverDevices(1);  //Discover a maximum of one device (saves waiting for whole inquiry period)
            Guid service = InTheHand.Net.Bluetooth.BluetoothService.RFCommProtocol; //UUID 0x0003
                       
            InTheHand.Net.Bluetooth.ServiceRecord[] rec = devices[0].GetServiceRecords(service); //Just so I can see the service record
            BluetoothWin32Authentication win = new BluetoothWin32Authentication(HandleAuth);
            
            bc.Connect(devices[0].DeviceAddress, service); 

            var peerStream = bc.GetStream();
            var st = new StreamReader(peerStream);
            var sw = new Stopwatch();
            var buffer = new int[1000000];
            var wr = new byte[1000000];
            var rand = new Random();

            for (int i = 0; i < 1000000; i++)             
                wr[i] = Convert.ToByte(rand.Next(128));
            
            sw.Start();
            peerStream.Write(wr, 0, 1000000);
            
            int streamPos = 0;

            while (!st.EndOfStream)
            {
                buffer[streamPos] = st.Read();
                streamPos++;
                if (streamPos == 1000000)      
                                 Console.WriteLine("Data transfer");   
            }

            sw.Stop();
            bc.Close();
            bc.Dispose();
The data will finish transferring (I can breakpoint on Console.WriteLine("Data transfer")), but when I continue to step through the code, it will return to the while(!st.EndOfStream), but if I try expanding the st stream and inspecting the member variables values they simpread
"Function evaluation disabled because a previous function evaluation timed out. You must continue execution to reenable function evaluation.".
Attemping to continue stepping through results in the whole application just hanging. What is happening?
I've tried using smaller amount of data but it still never gets out of the while loop. What do people think?

MS Stack
Windows 8.1
Generic USB dongle
Connecting to a BT chip running an RFCOMM server on a DevBoard

Thanks
Thomas

P.S The speed of my connection is only 0.76 MBit/s (took 10.5 seconds to transfer 1Mbyte0, which is fairly shoddy, considering the application throughput listed by BT 2.1 EDR is . Do I need to configure something the chip to set it into a higher speed?
Developer
Jan 9, 2014 at 12:16 PM
Edited Jan 13, 2014 at 3:49 PM
Later, it occurred to me why the first was hanging. Until the Stream is closed StreamReader.EndOfStream will return false. So since the connection was never closed the initial program would again call Read even after the last byte was received and hang forever waiting for more data.

In TCP/IP with TCP one could do a half close, that is close the Write/Send direction only and the Read on the peer would see end of stream. Its not possible to close one side of an RFCOMM connection in Bluetooth, so one just has to know how many bytes to read there.
OLD WRONG: I have_ no faith in many of the properties on Stream and StreamReader. In particular Stream.Connected and, StreamReader.EndOfStream. They are often misleading, for instance Stream.Connected reflects reality only after some user action https://32feet.codeplex.com/wikipage?title=Connected%20Property I suspect StreamReader.EndOfStream might be similar. For end of connection in Stream/TextReader I believe only the result of Read/etc. ...
... For your current test I'd use Stream directly. StreamReader ,i.e. TextReader is good for some things but get used to Stream first. Reading a byte at a time will also be slow which might be affecting you here.

Use the following style -- both to test, and in your real app something based on that. So 1) Stream, 2) Read(byte[],...) and 3) EoF is return value is zero;
  var buf = new byte[1000000 + 1000]; // 1000 just for testing
  while(true) {
     int readLen = strm.Read(buf, 0, buf.Length);
     Console.WriteLine("read num bytes: " + readLen);
          if (streamPos == 1000000) {     
                                 Console.WriteLine("Data transfer");   
        break;
    }
     if(readLen==0) {
Console.WriteLine("ERROR end of connection before receive transfer is complete.");
        break;
    }
  }
Alan

Notes
[1] https://32feet.codeplex.com/wikipage?title=Connected%20Property