Android Question UDP: multicast=packet loss, unicast=good

MolsonB

Member
Licensed User
Longtime User
I'm having an issue and not sure if it's an android problem or the device itself.
I have an ESP8266 acting as an access point with 2 android tablets connected to it right now.

When I send out to x.x.x.255, one tablet has over 30% packet loss, other is 1.2% (i'm ok with that amount of loss). If I send out unicast to just that one troubled tablet (10.10.10.100), it has barely any loss (< 0.2%). Sending only about 12 bytes @ 3 times a second, which isn't much. I bumped it up to 10 times a second, and both tablets error out about 30%.

Both are running rooted rom's with android 5.1.1
Samsung 10.1 P7500 (2010) ~1.2%
Samsung Tab A 7.0 SM-T280 (2015) >30%

I also plugged in my Samsung S5 (running stock 6.0.1 version), and had over 20% loss. Ran across the post about trying to lock a multicast state, and added it without any difference in performance. The newer devices are blocking some of the UDP packets?

Since I'll only have 4 tablets, I could send to each individual IP address.


Manifest
B4X:
'This code will be applied to the manifest file during compilation.
'You do not need to modify it in most cases.
'See this link for for more information: https://www.b4x.com/forum/showthread.php?p=78136
AddManifestText(
<uses-sdk android:minSdkVersion="5" android:targetSdkVersion="19"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
<supports-screens android:largeScreens="true"
    android:normalScreens="true"
    android:smallScreens="true"
    android:anyDensity="true"/>)
SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")
'End of default text.
AddPermission(android.permission.CHANGE_WIFI_MULTICAST_STATE)

Service - Starter
B4X:
#Region  Service Attributes
    #StartAtBoot: False
    #ExcludeFromLibrary: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Dim Tablet As Reflector
    Dim UDPSocket1 As UDPSocket
    Dim UDPPort As Int = 8888
  
End Sub

Sub Service_Create
    Tablet.Target = Tablet.GetContext
    Tablet.Target = Tablet.RunMethod2("getSystemService", "wifi", "java.lang.String")
    Tablet.Target = Tablet.RunMethod2("createMulticastLock", "mylock", "java.lang.String")
    Tablet.RunMethod2("setReferenceCounted", False, "java.lang.boolean")     'not really necessary but safer
    Tablet.RunMethod("acquire")                                            'acquire the lock

    'This is the program entry point.
    'This is a good place to load resources that are not specific to a single activity.
    c.BCMData.Initialize
End Sub

Sub Service_Start (StartingIntent As Intent)
    'Start receiving data
    If UDPSocket1.IsInitialized = False Then
        UDPSocket1.Initialize("UDP", UDPPort, 8192)
        Log("Listening for UDP packets on port "& UDPSocket1.Port)
    End If
End Sub

Sub Service_TaskRemoved
    'This event will be raised when the user removes the app from the recent apps list.
End Sub

'Return true to allow the OS default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

Sub Service_Destroy
    If UDPSocket1.IsInitialized Then
        UDPSocket1.Close
    End If
    Tablet.RunMethod("release")                        ' release when not needed to save battery  
End Sub



Sub UDP_PacketArrived (Packet As UDPPacket)

'Log(Packet.Length)
'    If Packet.Length <> 8 Then
'        Log("Invalid packet")
'    End If
    Dim PacketLength As Int
    Dim PacketId, x As Int
    Dim PacketValid As Int
  
    Dim raf As RandomAccessFile
    raf.Initialize3(Packet.Data, False)
    raf.CurrentPosition = Packet.Offset
  
    PacketLength = raf.ReadShort(raf.CurrentPosition)
    PacketId = raf.ReadUnsignedByte(raf.CurrentPosition)

    PacketValid = raf.ReadShort(raf.CurrentPosition)
    '2 byte rolls over from BCM
    If PacketValid = 65535 Then c.BCMData.RollOver = c.BCMData.RollOver + 1
    If c.BCMData.RollOver > 0 Then PacketValid = PacketValid * c.BCMData.RollOver
  
    Log(PacketValid)
  
    c.BCMData.Connect = True
  
    If c.BCMData.StartValid = 0 Then
        c.BCMData.StartValid = PacketValid            'Starting point when this app connected to bcm
    Else If c.BCMData.Valid > PacketValid Then
        Log("Wrong packet order "& PacketValid)
        c.BCMData.Invalid = c.BCMData.Invalid + 1
        Return    'The last packet ID is bigger then the current packet, skip
    Else If c.BCMData.Valid < (PacketValid - 1) Then
        Log("Missed packet "& (c.BCMData.Valid + 1))
        c.BCMData.Invalid = c.BCMData.Invalid + 1    'The last packet ID should equal the current packet - 1 (next Id in line)
    End If
    c.BCMData.Valid = PacketValid
      
    c.BCMData.NumConnects = raf.ReadUnsignedByte(raf.CurrentPosition)
    c.BCMData.ScreenDim = raf.ReadUnsignedByte(raf.CurrentPosition)

    x = raf.ReadUnsignedByte(raf.CurrentPosition)
    c.BCMData.DoorOpenLSw = Regex.IsMatch("1", Bit.And(x,Bit.ShiftLeft(1, 0)))
    c.BCMData.DoorOpenRSw = Regex.IsMatch("1", Bit.And(x,Bit.ShiftLeft(1, 1)))
    c.BCMData.FuelTransLSw = Regex.IsMatch("1", Bit.And(x,Bit.ShiftLeft(1, 2)))
    c.BCMData.FuelTransRSw = Regex.IsMatch("1", Bit.And(x,Bit.ShiftLeft(1, 3)))
  
    x = raf.ReadUnsignedByte(raf.CurrentPosition)  
    c.BCMData.FuelTransAuto = Regex.IsMatch("1", Bit.And(x,Bit.ShiftLeft(1, 0)))
    c.BCMData.FuelTransLRelay = Regex.IsMatch("1", Bit.And(x,Bit.ShiftLeft(1, 1)))
    c.BCMData.FuelTransRRelay = Regex.IsMatch("1", Bit.And(x,Bit.ShiftLeft(1, 2)))

    CallSub(Main, "DataRefresh_Tick")
End Sub
 
Last edited:

JakeBullet70

Well-Known Member
Licensed User
Longtime User
Many many years ago. (Think pre-iPhone, Android and Windows XP was the new kid on the block.) I did Enterprise UDP work on an AVOD (Audio Visual On Demand) system for private jets. I had over 150 computers I needed to get messages out to. Lots of testing and testing on packet loss. I did find that the more the underlying network was busy the more loss I had.

UDP is not guaranteed to arrive.
https://en.wikipedia.org/wiki/User_Datagram_Protocol

In the end. I sent each message about 4 times and each message a had a unique message ID so messages where not processed twice. That was the only way I got 99% delivery.
 
Upvote 0

MolsonB

Member
Licensed User
Longtime User
system for private jets
I like your style. The system is for my own experimental plane that will send Engine & Flight into to my android tablets. Cheaper then buying more glass displays from aviation companies. I knew UDP is guarantee packet loss, but I thought 30% was a tad wee high. Funny how the newer and faster devices I have, reported more packet loss then my old and slow tablet. I thought the tablets would 'accept' more packets on multicast vs broadcast, as it's more specific addressing. One approach I was going to try tonight, was to send the same message to each individual ip address. (I'll only have 4 devices max connected to ESP8266). They all seem to accept pretty much every unicast packet.

Why not switch to MQTT? You can run the broker on one of the Android devices.
I've come across the MQTT term a few nights ago but didn't fully read about it. I'll do some searching on the forum tonight and try a new sketch.
 
Upvote 0
Top