Networking with UDP

Blitz3D Forums/Blitz3D Programming/Networking with UDP

Kiyoshi(Posted February) [#1]
Hey all. I've got a dilemma here. I'm not sure I'm understanding or implementing this correctly. I'm messing around with UDP commands, trying to make a simple server/client program. Right now I'm going for a simple 3D world. Each client controls a sphere and can move around while seeing the others move as well.

I have three programs running: The Server, Client A, and Client B. Each one has a UDP stream used to communicate with. All three are regularly listening for data on their respective UDP stream, and each one will send an update about 10 times every second. A Client will send their coordinates to the Server, which then sends those coordinates to all other Clients.

What I'm not quite sure about is how the data is stored in a UDP stream. To my understanding, I write the data to the local UDP stream using WriteLine, WriteFloat, etc., and then send that data using SendUDPMsg to the correct clients. So, for example...

-Client A writes coordinate data to the local UDP stream, and sends it to the Server.
-Server receives data, and writes the proper data to it's own local UDP stream, and sends it to all other clients.
-Client B receives data, and positions Client A's 3D model using the coordinates received.

Using TCP I could assign a stream to each user on the server, and send the data on the respective streams from the server to the proper client. But each example I've found for UDP in the archives so far only uses one stream per instance, for two-way data transmission.

Server-side, example of what I've done in TCP in the past:
For U.User=each User
	If U\ID=SendID;This client is the one that needs data sent to it
		WriteByte(U\Stream,1);Byte to let the client know what sort of message it's receiving.
		WriteLine(U\Stream,"My message")
	EndIf
Next

Note that the above example allows me to send individual lines.


Server-side, what appears to be my only option for UDP:
For U.User=each User
	If U\ID=SendID;This client is the one that needs data sent to it
		WriteByte(ServerUDPStream,1);Byte to let the client know what sort of message it's receiving.
		WriteLine(ServerUDPStream,"My message")
		SendUDPMsg(ServerUDPStream,U\IP,PORT);Send the information written onto the client's stream
	EndIf
Next

This example has me send everything on ServerUDPStream at once.

Now, both of these examples work. The difference being, with TCP I can write directly to the user's stream. But with UDP, however, I have to write to the server's two-way local stream before sending the data to the proper client via SendUDPMsg. The reason I bring this point up is that the same stream appears to be used for both sending and receiving data. This brings me to my problem. What if the data in a stream is added to before the program can process it all?

When a Client sends their coordinate data to the Server, it's stored in the Server's UDP stream. Normally my Server can process all the information and send it where it needs to go before it receives another message from a different Client, but what if that isn't the case? For example:

-Client A sends coordinate data to the server, which contains X, Y, and Z info.
-Client B sends it's own coordinate data to the server at the same time.
-Server receives this data, and stores in ServerUDPStream.
-Server processes the first set of X, Y, and Z info for Client A
-Server then writes this data to ServerUDPStream to be sent to the other clients.
-Server then prepares to send the entire ServerUDPStream to all other clients, which contains Client A's coords.
-But wait! ServerUDPStream still has Client B's coordinate data within it...this should not be sent to all clients yet!

As far as I know, I can either send ALL of the data, or NONE of the data. I seem to have less control over the data using UDP than I did using TCP. With TCP I could write to each user's individual stream. This doesn't seem to be the case with UDP.

Ultimately, my question is simply, am I doing this wrong? Is there something I'm missing, or do I have to find a way to work around this? Is this absurdly simple and I'm blowing this out of proportion? Maybe I'm totally misunderstanding how this works and I'm mucking up the whole thing. If you have any input on this at all, I'd greatly appreciate it. The Blitz3D docs seem to be lacking in explaining how the UDP commands work, so anything you'd have to share would be wonderful.

Thanks for reading all this. I'm going to beat my head against the wall for a little bit.
-Kii


Matty(Posted February) [#2]
Correct me if I'm wrong but I've always maintained that with UDP you use a stream to receive on and a stream to send on - two separate streams.


Imperium(Posted February) [#3]
UDP also has no error checking. Could this explain whats going on? If a single bit is lost in transit without any coded error checking it will cause your program to be very unstable.

This might not tell you anything you don't already know, but thought it may help:

TCP (Transmission Control Protocol) is the most commonly used protocol on the Internet. The reason for this is because TCP offers error correction. When the TCP protocol is used there is a "guaranteed delivery." This is due largely in part to a method called "flow control." Flow control determines when data needs to be re-sent, and stops the flow of data until previous packets are successfully transferred. This works because if a packet of data is sent, a collision may occur. When this happens, the client re-requests the packet from the server until the whole packet is complete and is identical to its original.

UDP (User Datagram Protocol) is anther commonly used protocol on the Internet. However, UDP is never used to send important data such as webpages, database information, etc; UDP is commonly used for streaming audio and video. Streaming media such as Windows Media audio files (.WMA) , Real Player (.RM), and others use UDP because it offers speed! The reason UDP is faster than TCP is because there is no form of flow control or error correction. The data sent over the Internet is affected by collisions, and errors will be present. Remember that UDP is only concerned with speed. This is the main reason why streaming media is not high quality.


Matty(Posted February) [#4]
UDP does not send 'broken packets'...you either receive a full packet or nothing but the order of transmission or whether the whole packet arrives is not guaranteed....you will not lose single bits.


Kiyoshi(Posted February) [#5]
Apologies for any confusion. I understand the technical differences between TCP and UDP. What I believe I'm misunderstanding is how the commands work in Blitz3D. The two examples I found both appear to use a single handle for receiving and sending, i.e. UDPStreamA receives the data from UDPStreamB, and UDPStreamA is also used to hold the data to send to UDPStreamB as well. Although the data is sent to the destination on a separate stream, it appears that I'm limited to one local UDP stream for handling that data until it's transmitted.

Again, I really feel like I'm absurdly wrong about this, but I can't find much else in the way of documentation to help me out. I'm apologize if I'm not explaining this correctly, or not making any sense.


grable(Posted February) [#6]
Blitz3D UDPStreams have separate buffers for input and output, so it should be safe to use only one handle for the server, if that is what you want.

But there is nothing stopping you from creating a dedicated outgoing stream and simply ignore any inbound messages.
You could even allocate a port/stream for each client if you wanted (within reason of course)


Kiyoshi(Posted March) [#7]
Thanks for all your input, everyone, I appreciate it. I've figured it out, just had one of those days I suppose.

@grable: I think this is what had me confused. Thank you for clearing that up for me.

-Kii