inthehand / 32feet

Personal Area Networking for .NET. Open source and professionally supported
https://inthehand.com/components/32feet/
MIT License
826 stars 209 forks source link

Issues getting bytes from `stream.Read(...)` #80

Open h2oboi89 opened 4 years ago

h2oboi89 commented 4 years ago

Using 32fee.NET v3.5.0 from Nuget (using .NET 4.5) I am having some issues getting bytes from the device I am connecting to.

Connecting to device

var client = new BluetoothClient();

foreach (var device in client.DiscoverDevices(0xff, true, false, false);)
{
    if (regex.IsMatch(device.DeviceName))
    {
        try
        {
            client.Connect(device.DeviceAddress, BluetoothService.SerialPort);
        }
        catch (SocketException) { }

        if (client.Connected)
        {
            return new BluetoothGeaNode(client, device.DeviceName);
        }
    }
}

client.Dispose();

return null;

I am reliable able to connect to a device that matches the user input regex (usually ".*").

Getting bytes from device

var stream = client.GetStream();

new Thread(() => {
    while(true) {
      var bytesRead = stream.Read(buffer, 0, buffer.Length);

      Console.WriteLine($"<- {Hex.ToHexString(buffer)}");

      if (bytesRead > 0) { /* Do stuff with bytes */ }
      else { break; }
    }

    // emit disconnect and dispose of client and stream
});

When stream.Read works it works great, but the majority of the time it just blocks and never returns any bytes, even though I am able to send bytes to the device that I can confirm get sent as I am monitoring traffic on that end. That end is also sending responses that seem to make it to my device, but not to my PC.

If I disable bluetooth via the Windows notifications grid while it is blocked not getting data I will get one buffer of all zeroes.

Do you have any potential insight into this?

peterfoot commented 4 years ago

How big is the buffer you are using? If this is too big you have to wait until it is full before the Read completes. Try setting a smaller buffer or use the Socket directly which has more options for reading (you can configure it to return a partial read rather than waiting for a full buffer).

h2oboi89 commented 4 years ago

It is only 1097 bytes (maximum single payload size). And when it works I get partial buffers just fine. I let it run for a while before declaring failure, which should be more than enough to fill a single buffer as well.

Example:

0x46CCE8D7F3CE4959000F3BE40BEC0109080706050403020100E3E2EC0FE4010001020304050684AFE3010203045A20E30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
thhowl commented 4 years ago

FWIW, I'm having success in .Net Standard 2.0 > Android, with StreamReader and ReadAsync, and various sizes of data:

_stream = _client.GetStream(); _streamReader = new StreamReader(_stream, Encoding.ASCII); var readCount = await _streamReader.ReadAsync(_streamReaderCharBuffer, index: 0, _bufferSize);

(not the exact code, but the essence of it)