I'm developing the client-server Winsock app (Visual C++) that should transmit the various kind of data (video stream, audio stream, service notifications, etc.) over the network. I know that the cleaner approach would be to use separate ports on separate threads for each individual data type (I call it "stream" here). But that would require occupying at least 5 different ports that would get problematic for some network infrastructures (firewall port forwarding, etc.).
So I'm trying to implement one-port connection (TCP), only one socket will be used to transmit different streams. The individual packets will have the info in header that will denote which stream it belongs to, total message size to be expected, etc. Say I have 5 different streams. I'm planning to use 5 threads to call send() of the same socket. Is this safe? I know the packets from different streams will arrive mixed but if I include necessary meta information in each sent packet, it could be reconstructed properly on the other side, right?
But the real problem is the receiving end. While it's probably OK to call send() from multiple threads on the same socket (though I'm not sure and need your confirmation!), calling recv() from multiple threads would not make much sense. So I should use one blocking recv() from one thread. But then, based on the packet header (identifying which stream the particular packet belongs to) I should fork the processing in different threads. Video stream should be processed by one thread, sound stream - by another, etc. But I don't quite know how to do this - how to fork the data processing from the receiving thread. Performance is a top priority so processing all streams by one thread can't be considered.
So to sum it up, I have three questions:
- Is it OK to call send() for same socket from multiple threads? (assuming there will be info in packet header about which sender thread (i.e. subsystem) it belongs).
- Having one blocking socket on the receiving end, calling recv() in loop from a single thread, how to "fork" the received packets of different logical streams to different worker threads?
- What would be your additional recommendations for implementing multiple-stream transfer through one port?
P.S.: Afaik, there's no way to use one port by multiple sockets, correct?
It's Windows platform, Winsock2, Visual C++ (if you could provide platform-specific hints that would be awesome).
= UPDATE =
When you say to "lock socket", you mean serialize the access to send() function? e.g. with Critical Section?
As for receiving end... I think I'll assemble messages (I call "message" the logical complete data structure, e.g. video frame, or sound sample, etc.) when recv()-ing them in loop (buffering messages from individual streams into individual buffers), and then I just pass the assembled messages (when one will be fully received), to forking threads. Now that is the question - how to pass them. The one way I've thought of is Event Objects: SetEvent() from receiver thread to trigger WaitForSingleObject() (which is in some loop) in different threads. Can you advice if this is the acceptable solution? Can you suggest anything better? Aren't there any faster solutions to do this ("trigger" another thread of the same application) than Event Objects? And how to pass the data?