Quote:Original post by sheep19
Do you mean something like this?
*** Source Snippet Removed ***
The idea is right, but the implementation is still flawed. Expanding on what hplus0603 mentioned, you may not actually get all of the bytes you ask for in TCP since it's a stream protocol. More specifically:
Quote:SDLNet_TCP_Recv gets available data that has been received on the socket. Up to maxlen bytes of data is read and stored in the location referenced by data. If no data has been received on the socket, this routine waits (blocks) until some comes in. The actual number of bytes copied into the location may be less than maxlen bytes.
So it is very possible that you won't actually get the full fields worth of data for each of your SDLNet_TCP_Recv calls. This means the data is incomplete and your program state becomes corrupted. Worse of all, such bugs can exist and never show themselves until you get into high latency situations or data processing slowdowns and then you are left wondering what is wrong with your program!
So what you really need to do is implement different stream processing logic for your program. Simply call SDLNet_TCP_Recv with a generic char buffer and save it to the client object's stream. After each of those reads, check to see if you have enough bytes to process each field. Once you do, then you can process each field and know when you have a complete message. This type of logic requires that you use some other SDLNet_ API functions though. In your current design, if a client happened to not send all of the data, your program will simply hang while it's waiting for data (assuming you aren't using threads). This is also in expansion to the 2nd part of hplus0603's response.
One more note, if you use size_t, then your 32bit/64bit server/client programs will (most likely) be incompatible with each other. That is because size_t is (usually at least) 4 bytes on 32-bit and (usually at least) 8 bytes on 64-bit. The packet data will be of different sizes in each case, so you should use a data type that will be the same size on both 32-bit and 64-bit to ensure you don't suffer from such issues when doing network programming (specifically portable types).
Lastly, the clients should not really be time stamping their own messages. In such a design, someone could fake the time stamps to make their messages appear at any time they wish. It really serves no purpose because you can just time stamp on the server when it actually receives the chat message. I.e., imagine what would happen if the government let everyone use their own postmarks on mail!
So to wrap up, you need to expand your use of the SDL_Net API to get polled/non-blocking socket operations as well as change up your TCP stream processing. Before you construct a string from the data and save it though, you should also be doing data validation so you don't run into any issues. For example, what if a client were to send a string of invalid characters?
I'm not sure if you have to use SDL_net, but you might want to consider checking into
boost::asio as well. It certainly has a steeper learning curve and might take some extra work to get setup if you are new to boost, but it is well worth it. It helps solve a lot of TCP nuances for you through their API command set (i.e., they have functions that will wait for all TCP data per read and write so you don't have to mess with it yourself). best of all, they even have a
chat example you can look through to get an idea of how it'd work (their example is not perfect, but it's just an example).
It may seem kind of overkill for such a small program, but if you are going to be getting into more complicated TCP network programs or plan on spending more time network programming, the time is well spent with boost::asio, in my opinion. [wink] Good luck!