Receiving confirmation

Eduardo Gomez 4,156 Reputation points
2025-10-04T21:07:23.08+00:00

So, I finally finished, the Widows send data part, and I am waiting for confirmation

Windows implementation

  /// <summary>
  /// Sends raw byte data over the active RFCOMM connection and waits for acknowledgment.
  /// </summary>
  /// <param name="data">Byte array to send.</param>
  /// <returns>True if the data was sent and an acknowledgment was received, otherwise false.</returns>
  public async Task<bool> SendDataAsync(byte[] data) {
      DataWriter? writer = null;
      DataReader? reader = null;
      try {
          if(_socket == null || _socket.OutputStream == null || _socket.InputStream == null) {
              Debug.WriteLine("[WARN] SendDataAsync: socket is null or disposed");
              return false;
          }

          // --- Send Data ---
          writer = new DataWriter(_socket.OutputStream);
          writer.WriteBytes(data);
          await writer.StoreAsync();
          await writer.FlushAsync();
          Debug.WriteLine($"[INFO] Sent {data.Length} bytes: {Encoding.UTF8.GetString(data)}");

          // --- Wait for Acknowledgment ---
          reader = new DataReader(_socket.InputStream);
          reader.InputStreamOptions = InputStreamOptions.Partial;

          var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(8));

          try {
              // Read available data (flexible size)
              var bytesRead = await reader.LoadAsync(1024).AsTask(cancellationTokenSource.Token);

              if(bytesRead >= 2) {
                  string response = reader.ReadString(bytesRead).Trim();
                  Debug.WriteLine($"[INFO] Received acknowledgment: '{response}'");

                  if(response.Contains("OK")) {
                      Debug.WriteLine("[SUCCESS] Data delivery confirmed!");
                      return true;
                  }
              }
              else {
                  Debug.WriteLine($"[WARN] Received only {bytesRead} bytes, expected at least 2");
              }
          } catch(TaskCanceledException) {
              Debug.WriteLine("[ERROR] Timeout waiting for acknowledgment");
          } catch(Exception readEx) {
              Debug.WriteLine($"[ERROR] Failed to read acknowledgment: {readEx.Message}");
          }

          return false;

      } catch(Exception ex) {
          Debug.WriteLine($"[ERROR] SendDataAsync failed: {ex.Message}");
          return false;
      } finally {
          // Proper cleanup
          try {
              writer?.DetachStream();
              writer?.Dispose();
          } catch { }

          try {
              reader?.DetachStream();
              reader?.Dispose();
          } catch { }
      }
  }


Android listener

Android code

 public async Task StartListeningAsync() {
     var sppUuid = Java.Util.UUID.FromString("00001101-0000-1000-8000-00805F9B34FB");
     var serverSocket = BluetoothAdapter.DefaultAdapter.ListenUsingRfcommWithServiceRecord("SnapLabel", sppUuid);

     ShowToast("📡 Listening for Bluetooth...");

     while(true) {
         try {
             var socket = await serverSocket.AcceptAsync();
             ShowToast("🔗 Connected to PC");

             var buffer = new byte[1024];
             int bytesRead = await socket.InputStream.ReadAsync(buffer, 0, buffer.Length);
             string received = Encoding.UTF8.GetString(buffer, 0, bytesRead);
             ShowToast($"📥 Received: {received}");

             var echo = Encoding.UTF8.GetBytes("OK");
             await socket.OutputStream.WriteAsync(echo, 0, echo.Length);
             await socket.OutputStream.FlushAsync();
             ShowToast("📤 Echo sent: OK");

             await Task.Delay(1000000); // ⏳ Give Windows time to read
             socket.Close();
         } catch(Exception ex) {
             ShowToast($"❌ Error: {ex.Message}");
         }
     }
 }


VM

var success = await _bluetoothService!.SendDataAsync(Encoding.ASCII.GetBytes("Hello Printer\n"));
if(success)
{
	Debug.WriteLine("[SUCCESS] ✅ Data sent and delivery confirmed!");
}
	else 
{
    Debug.WriteLine("[FAILED] ❌ Data send failed or no confirmation received");
}
Windows development | Windows App SDK
0 comments No comments
{count} votes

Answer accepted by question author
  1. Michael Le (WICLOUD CORPORATION) 6,420 Reputation points Microsoft External Staff Moderator
    2025-10-06T03:58:05.51+00:00

    Hello @Eduardo Gomez ,

    Thank you for reaching out. I'm glad to hear that your development is going well.

    An established connection was aborted by the software in your host machine.

    This indicates that the remote computer actively closed the connection. This usually happens when there is no application on the receiving end listening for that specific Bluetooth connection, or if a security setting (like a firewall) blocked it.

    not Auth or socket

    And the error you see on your phone's Bluetooth terminal app suggests that the app itself was not able to properly accept the incoming connection or data, which is consistent with the issue.

    To get a true confirmation of delivery, you need to implement a simple acknowledgment protocol. The concept is similar to a "ping" as you mentioned. After your application sends data, it should wait for the receiving application to send a confirmation message back.

    I have modified your SendDataAsync method to include this logic. It will now send the data and then wait up to 5 seconds for a simple "OK" text response from the remote device.

    // ...existing code...
            /// <summary>
            /// Sends raw byte data over the active RFCOMM connection and waits for a simple acknowledgment.
            /// </summary>
            /// <param name="data">Byte array to send.</param>
            /// <returns>True if the data was sent and an acknowledgment was received, otherwise false.</returns>
            public async Task<bool> SendDataAsync(byte[] data) {
                DataWriter? writer = null;
                DataReader? reader = null;
                try {
                    if(_socket == null || _socket.OutputStream == null || _socket.InputStream == null) {
                        Debug.WriteLine("[WARN] SendDataAsync: socket is null or disposed");
                        return false;
                    }
     
                    // --- Sending Data ---
                    writer = new DataWriter(_socket.OutputStream);
                    writer.WriteBytes(data);
                    await writer.StoreAsync();
                    await writer.FlushAsync();
                    writer.DetachStream(); // Prevent writer from closing the stream
     
                    // --- Waiting for Acknowledgment (ACK) ---
                    reader = new DataReader(_socket.InputStream);
                    reader.InputStreamOptions = InputStreamOptions.Partial; // Read data as it comes
     
                    // Set a timeout for waiting for the ACK
                    var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(5));
                   
                    // Expecting a 2-byte "OK" response
                    uint expectedAckLength = 2;
                    var bytesRead = await reader.LoadAsync(expectedAckLength).AsTask(cancellationTokenSource.Token);
     
                    if (bytesRead >= expectedAckLength) {
                        string response = reader.ReadString(bytesRead);
                        if (response == "OK") {
                            Debug.WriteLine("[INFO] Acknowledgment 'OK' received.");
                            reader.DetachStream();
                            return true;
                        }
                    }
                   
                    Debug.WriteLine("[WARN] Did not receive expected acknowledgment.");
                    return false;
     
                } catch (TaskCanceledException) {
                    Debug.WriteLine("[ERROR] SendDataAsync timed out waiting for acknowledgment.");
                    return false;
                } catch(Exception ex) {
                    Debug.WriteLine($"[ERROR] SendDataAsync failed: {ex.Message}");
                    return false;
                } finally {
                    // Dispose writer but not reader, as its stream is detached
                    writer?.Dispose();
                    // Do not dispose the reader directly if you detached the stream,
                    // as the underlying socket stream should remain open.
                }
            }
     
     
            /// <summary>
    // ...existing code...
    

    Important: For this to work, the application on the receiving device (e.g., your phone's Bluetooth terminal app or a custom app on another computer) must be programmed to read the incoming data and then immediately send the two characters OK back over the same connection.

    I hope this helps. Let me know if you have any further questions.


0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.