I am currently plannng a stratagy for implementing multiple sockets (dozens to hundreds) as both a client and a server in my current MQX / MPC-5125 project (256MB DDR ram). I have a basic concept in place but I am curious what others who have faced this situation have done, how those decisions worked out and what you might do differently next time.
For this discussion I will treat sockets created as a server (from a listen task) and sockets created as a client (call to connect) as the same. Once I have these sockets connecting my app to other requried devices established, the communications requriements for each are similar.
First, the easy part (I think). Each socket will be supported by a dedicated MQX receive task, handling the call to recv() as a blocking function and a dedicated/fixed size RxBuffer that will be checked for waiting data from a different task. If recv() detects an error or socket closure, the task will terminate (closing the socket and freeing resources) and another connection will be attempted if appropriate.
Now the more challanging part, socket transmissions (Tx). Some outbound transmissions will be required to go out all acticve sockets, others to a single socket. It will also be necessary to take all possible precautions against a hung socket stalling communications with other sockets.
Here's my plan for outbound data transmissions:
1. For all transmissions, a dedicated MQX task will be created to service a call to send() for each socket. This task will only exist for the duration of the transmission then it will terminate.
2. Each socket will have it's own TxBuffer, implemented as a circular, rotating buffer. When this buffer is emptied, the TxTask will self terminate. To use this, data would be loaded into the buffer and then the MQX TxTask would be created. This task would take data from the circular, rotating TxBuffer assigned to the socket and transfer it in 1K chunks to a fifo byte array and call send(), repeating this process until all data has been sent.
3. The reason for the circular, rotating buffers here is so that an outside task can add additional messages to the TxBuffer (by moving the buffer InPointer) while the MQX TxTask is taking data out of the buffer using the buffer OutPointer.
4. In addition to the individual TxBuffers allocated to each socket, a single, "Global TxBuffer" (implemented as a fifo) will exist that can be loaded with a message intended for "all sockets". To use this, code must first check that it's not already in use. Then data is loaded in and an MQX task will be created for each socket that is to participate in the transmission. This transmit task will be simplier as it just passes send() a pointer to the buffer and waits for that function to return. When recv() returns, the transmit tasks will indicate they are finished with the "GlobalTxBuffer" buffer and self terminate.
5. If the "Global TxBuffer" is not available (maybe some socket has hung ?), the message data could still be loaded into each sockets individual TxBuffer as per item 2. Then steps could be taken to determine why the "Global TxBuffer" is busy. Maybe a socket is taking to long to transmit and has to be forced closed? Maybe a large message was just loaded and all is ok.
Does anybody have any other solutions to this situation? Maybe I'm making too much out of the possibility of a stalled socket? Does anybody see vulnerabilities here that I need to watch out for? This solution could result in a large number of MQX tasks (dozens to hundreds) being created. Is this a bad idea? Thanks for any helpful comments!