Use two separate parallel loops.
Loop 1 is your communication loop. When it gets a command from TCP/IP, it queues up a command in a queue.
Loop 2 is your DAQ/State machine. It dequeues the command from the queue with no timeout. If the dequeue function does not timeout and gets a command, it does whatever the command tells it to, possibly changing the next state of the state machine. States could be start DAQ, acquire DAQ, stop DAQ, Idle. If the function does timeout, it executes the current state. In the IDLE state, you may want to have it change the timeout of the dequeue function to something larger so that it doesn't spin the loop endlessly in the event nothing happens. Then decrease the timeout of the dequeue to 0 in the start DAQ so that the loop runs as quickly as it needs to to process the DAQ read functions.
As you expand to logging, you will want to have a second queue passing the data to be logged to a third loop.
I'm sure there are other ways to execute this architecture, this is the first that came to my mind.