Does TCPClient just suck in general?


I’ve been tearing my hair out trying to discover why it’s so weird. Like, why does available() block for 100ms? Why when I read one byte at a time do I get all the data I’m trying to read, but if I read multiple bytes at a time into a buffer it behaves so annoyingly… like, available() says there are 150 bytes, and I do a read() for 64, but it only returns 38? Are other people successfully using TCPClient? I see a lot of trouble reports going back to 2013, but it’s not clear to me how much is still applicable. Should I just use Particle.function()s and give up on TCP? Thanks for any advice.


A lot will depend on your device and system firmware version.

For Wi-Fi devices (Photon, P1), 0.6.3 is probably the best for TCP, followed by 0.8.0-rc.11. In 0.7.0, the WICED library that implements the Wi-Fi and TCP stack was upgraded, and it included a change in the IP stack that caused some unexpected changes in behavior. Much of this was straightened out in by the later 0.8.0-rc versions.

For cellular devices, you’re at the whim of the cellular modem module. My guess is that you are using a cellular device if available() is blocking, because it needs to query the modem. Performance there will depend on whether you use SYSTEM_THREAD(ENABLED) or not. I’d definitely recommend it if using TCPClient.

In any case, you’ll get much better performance if you always attempt to read a full 1024 bytes of data on read and never call available().


Thanks for this. I’m using an Electron/e-series running 0.8.0-rc.10. Does it really take 100ms to talk to the modem? I will try refactoring the code to read bigger blocks.


No, it won’t always take that long, but modem operations are generally synchronous and happen only on one thread (either the system thread or the application thread depending on SYSTEM_THREAD mode) and it’s possible that you can get blocked waiting for a shared resource.


Oh yeah I forgot to mention that I’m running with SYSTEM_THREAD(ENABLED), so I was assuming that I wouldn’t block… that either there would be bytes I can pull from the buffer, or not.