We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I have written a small embedded TCP/IP server application but it needs to work lock-step: one query then one response.
My problem is that the client (not under my control) making the requests is running ahead and I don't have the resources to buffer-up an arbitrarily large number of queries.
When a query comes in to the server, it arrives in the tcp_callback function. Data is arriving before I've fully sent the response to the previous one.
How do I impose some flow control on incoming data so that I can do things lock-step ?
This isn't a question about TCP/IP in general. It really needs to be answered by someone who knows or has used the TcpNet subsystem in the RL-ARM.
The situation is this. TcpNet is a very minimalist implementation of TCP/IP. According to the "framework" examples provided by Keil, you have to structure your program in a very specific way. After initialisation, your program's main loop basically has to run like this:
void main_loop() { main_TcpNet(); timer_Task(); clock_application_state_machine(); } U16 tcp_callback(..event data..) { }
and that's it. All the above works in a single thread. The actual transmission of packets is handled by the timer task. The higher levels of the TC protocol are handled in main_TcpNet()
TcpNet doesn't maintain a pipeline of outgoing packets: it only allows one packet in flight at once. This is why it is so slow (not a problem for me)
Also, it doesn't maintain a pipeline of incoming packets. Once an incoming packet has hit the network layer, it *must* call the callback, and I *have* to be prepared to handle it.
All I need is some method whereby I can return some value from the callback saying "I can't handle this packet; please throttle". The callback, however, does not take notice of any value returned from this event.
My clock_application_state_machine() runs the business part of my program.
The callback function provides notification on a few things: a) connection of the TCP socket b) closing of the TCP socket c) incoming TCP packet d) acknowledgement of the sending of a TCP packet.
My clock_application_state_machine() is generally kicked-off by the connection of a TCP socket. It then collects incoming packets and parses the incoming request. The results of this request move the state machine into a different state where it transmits the result, with the (d) above moving it from "waiting for ack" to "sending next packet".
This proceeds until the end of the request, whereupon it can receive another one.
The problem is that I CAN'T STOP DATA COMING IN, even though TCP has this facility naturally. As soon as one request has come in, a new one can come in, and another, and another, and another, when the state machine is still transmitting the result of several requests back.
of course you can stop data from coming in - just disable the respective interrupt for a short while. the client will eventually retransmit, because it won't receive an ACK from you for that packet. how about that? and of course you can manipulate the size of the sliding window and suggested here already, but at a performance cost.