TCPSocket MacOS vs Windows

I have a cross-platform app I wrote in Xojo. Uses TCPSockets.

Works fine in MacOS, but chokes on Windows.

It’s receiving a data via TCPSocket, and all is well until a large packet arrives. (1460 bytes). The TCPSocket in MacOS receives it properly, but in Windows, it receives only 1308 bytes.

Using Wireshark I can see the difference and an indication of the error in Windows, but I’m no networking expert and can barely figure out Wireshark.

My questions:
Does maybe the Windows TCPSocket have a smaller buffer or something?
Is there something different I have to do on Windows with TCPSockets for large packets?

Hopefully someone has run into this and can offer some suggestions. Thanks!

Can you paste versions with the IP Header expanded please? I am wondering if the DF bit is set on your windows trace.

What version of Windows are you using?

Are these traces both from your same location - is this location home or corporate network?

Thanks

never never never assume that a “packet” sent will be received as one unit
this is almost NEVER true and assuming it will cause issues

Chunks baby - chunks :slight_smile:

Ok, this is weird. On a separate Windows install on the same computer, it seems to be working.
Something funky, I’d love to know what in case I have users finding the same problem.

Windows 7 x64, and MacOS Mojave, same network home network (wired), speaking to the same device.

I’ll post some more screenshots once I fully test this seemingly working copy.

different network adapter different buffer sizes etc etc etc

and, you can get seemingly random results IF you assume that what got sent from one end arrives at the other in ONE data available event

mostly it wont

Figured it out.

2 different versions of network drivers. The one that didn’t work had Jumbo Frames enabled. I would have to guess that the hardware device doesn’t support Jumbo Frames. Oddly, they are both the same version, but one has more settings than the other. Friggin Windows!!

Bad Driver:

Good Driver:
Good Network Driver

Disabling Jumbo Frames fixed the problem. WHEW!!

That might fix THIS problem but if / when the data you send get larger you’ll have the problem again
Data available makes NO guarantee all data arrive in one event
Neither does TCP

So heads up

No worries, Norm. I wrote into the handler how to deal with partial messages.

Is there a way to detect whether or not jumbo packets are enabled? Since it produces no error, (the device just quits sending), it would be great if I can check that setting on a users computer…

I dont know of a way to detect it
Possibly a registry setting ?
I’ve seen mention of those but that might be specific to whatever adapter is in use

Maybe netsh from the cmd line can tell ?
On newer Windows you probably need to use PowerShell

Get-NetIPInterface more than likely (or something in that vein)

1 Like

Disabling Jumbo frames is not a good solution - yes it works, but it will break again soon with someone else’s windows box. Thats where I was heading with your traces seeing if your DF (Dont fragment) bit was set in Windows – Windows used to have bad bad issues trying to detect a path MTU (PTMUD) which always set the DF bit to True on PMTUD failure causing larger frames to be discarded when they needed to be fragmented at the next hop layer 3 boundary.

You just need to query the MTU of the Windows Driver Interface to detect Jumbo or not. Anything > 1500 is Jumbo (Usually its 9000 mtu for Jumbo)

Here are the easy steps I took to do it in Windows 10 .

  1. Open a command prompt as administrator. ( …
  2. type the command : netsh interface ipv4 show subinterfaces.
  3. This should output your interfaces and current MTU size.

Thank you, Mike for that information! Since users will be using this software on unknown machines, it would be great to see if there’s a way to head off potential problems. Really appreciate your help.

Here is the Wireshark capture, if you can make heads or tails of it!
Wireshark Capture

Ultimately, if it turns out that the hardware device does not support Jumbo Frames, it would be great if I could detect whether the user’s computer had them enabled and give a warning. This would need to work cross-platform, Win/Mac/Linux of course… :wink:

That makes sense – Your IP header DF bit is set to “don’t fragment” (Flags 0x4000) so any frame coming in with link layer / upper layer headers over 1500 will drop at the NIC.

I think the thing to do like Norman said above is to try to detect if yoru Windows NIC has an MTU capable of 9000 MTU (jumbo frames) or not (1500 MTU). If not then you know what you can do already its seems in code. Im not a super windows dude anymore so ill end this post but look to see if there is a way with netsh to query your NIC to see if you NIC can do above 1500 or not. (light reading on it: https://en.wikipedia.org/wiki/Path_MTU_Discovery)

Ok Two Ideas:

  1. This link shows how to use netsh to get the existing MTU of the NIC https://cpsdocs.dellemc.com/bundle/VXF_CONF_CUST/page/GUID-237194FA-AB9B-4594-80FA-D10EEA40DF87.html

  2. You could also do a (OS X: ping -s 2000 127.0.0.1 [IP of said NIC] ) or (Win: ping -l 2000 127.0.0.1 [IP of said NIC]) to see if you get a valid response. Valid = Jumbo is enabled and Not = 1500 MTU.

I am still trying to see if there is a command to query Jumbo frame support boolean for a NIC.

In my experience Windows is notorious at sucking with MTU discovery.

Ok Try this (I dont have my windows box handy).

Apparently this command result is supposed to have the NICs capabilities. I am hoping jumbo frame support is one of them.

  1. Power shell command to query jumbo frame capability:
    Get-NetAdapterAdvancedProperty -Name

  2. Power shell command #2 (untested)
    Set-NetAdapterAdvancedProperty -Name “ISCSI” -RegistryKeyword “*JumboPacket”

Good luck and let us know how you end up on this.

  • Mike

Thanks, Mike.

Just in case it’s not clear, the issue is not with the computer’s NIC, but with the hardware’s NIC, where it doesn’t seem to support Jumbo Frames.
All I’m looking for is a simple test to see whether or not the person’s computer’s NIC is set up with Jumbo Frames, and to give a warning if it is, as the program will fail. The ping command will always fail with anything > 1500 because the Hardware device doesn’t support it. Whether the NIC in the computer supports it is not the issue, just whether it has them enabled.

Mark,

Please clarify what the “hardware’s NIC” is if its not the computer your software is running on? Thanks bud.

My software connects to a digital mixer via ethernet. The “Hardware’s NIC” is the NIC on that digital mixer. It is not configurable in any way, so my software has to accommodate it, and that means no jumbo frames, it seems.

When a customer uses my software, I would like to check their computer’s NIC to see if it has Jumbo frames enabled, and if it does, to warn them that the software will not work until they disable that.

1 Like

Here’s my crude solution…

Private Function CheckMTU() As Integer
   Dim s As New Shell
   Dim r As New RegEx
   Dim Fields() As String
   Dim Index As Integer

   If TargetWindows Then
     s.Execute("netsh interface ipv4 show interfaces | find " + Chr(34) + " connected" + Chr(34) + _
        " | find /v " + Chr(34) + "Loopback" + Chr(34))
     Index = 3
   Elseif TargetMacOS Then
     s.Execute("ifconfig | grep flags=8863 | grep -v bridge | grep -o 'mtu.*'")
     Index = 1
   Elseif TargetLinux Then
     s.Execute("ifconfig | grep flags=4163 | grep -v bridge | grep -o 'mtu.*'")
     Index = 1
   End If

   If s.ErrorCode = 0 Then
     r.SearchPattern = ("\s+")
     r.ReplacementPattern = Chr(9)
     r.Options.ReplaceAllMatches = True
     Fields = r.Replace(s.Result).Split(Chr(9))
     Return Val(Fields(Index))
   Else
     Return -1
   End If
End Function

It would be better if I could pass it a socket and it would check that one specifically… If there’s multiple active interfaces, it’s just returning the MTU of the 1st one…

a connected socket has a networkinterface property and that can tell you which address etc it on

havent checked any of the commands in your code to see if you could use that to find the right one but it seems plausible