Networking 101

Blitz3D Forums/Blitz3D Programming/Networking 101

Adam Novagen(Posted 2011) [#1]
I've been in a bit of a slump this month for programming, and it's been putting a major spanner in the works for getting my game together. To refresh myself, I'm taking up a side project for fun, and also to take my first foray into multiplayer principles. It's doing the trick as far as my brainwork and enthusiasm go, but I'm at a bit of a loss with this project on several fronts since I basically know nuffink about networking whatsoever. So, here come the questions.

Is it possible to obtain an external IP from B3D? I know (or at least believe) this can be done server-side with TCPStreamIP(), but I was wondering if there was any way for a client to know its own external IP address, rather than just its LAN IP. And yes, I know I could simply send the IP address detected by the server back to the client, but if possible I'd like to get the outside IP without using external sources. Risk of proxies and all that.

Can more than one TCP stream exist safely on the same port? In other words, if the server is listening for incoming streams on port 32587, and the client is sending its data to that port, can any other clients do the same? Or is it necessary to somehow assign each client its own port? I can't honestly imagine the latter being the case, but since I'm a complete novice here I figured it'd be safer to ask.

What would be a good way to handle large-ish file transmissions alongside player data? What I'm aiming for here is a "custom content" system. Say that the server is modified in some way or uses some sort of custom content; when a player connects, it needs to send a few images or what-have-you to their client, but it must do this while causing as little throttling on the already-connected players as possible. Should I simply use a MilliSecs() timing step to juggle the file transfer with the player data? Should I split the server into two separate programs, one to handle custom content transmissions and one to handle the player connections? Is there some other trick or ploy I don't know about yet, or should I simply forget the idea of custom content while using B3D?

That's about all I can think of for the moment, and it'll certainly give me a bit to chew on. Cheers!


Leon Drake(Posted 2011) [#2]
yes you can get your external ip,

but i would recommend UDP over TCP for gaming.


Rroff(Posted 2011) [#3]
TCP is very slow in B3D (and in general) handshaking a new connection will stall the main thread for 200ms or so - so short of using threading with fastpointer its usually best avoided aside from things like downloading a new map file from a web server in the game client.

Getting the external IP on the client without bouncing off a remote server can be quite hard depending on the specifics of what the client is running.

If you want to handle custom content from the server I would reccomend doing one of the following:

URL redirect where the server hands the connected client a URL to a web server where it can download the data from as a file.

Seperate thread(s) on the server software using fastpointer that is purely used for handling content downloads to clients.

Last edited 2011


Adam Novagen(Posted 2011) [#4]
I've heard, but fortunately there's very little action element in this. Actually I'm trying something in a retro-RPG style, so the movement is tile-by-tile grid based, and combat uses minimal time orientation. In this case, I believe I would be better off with the stability of TCP over the relative speed of UDP. That raises a fourth and fifth question, though, namely "Should I use UDP instead of TCP" and "If so, how would I implement it?"


RifRaf(Posted 2011) [#5]
What would be a good way to handle large-ish file transmissions alongside player data? What I'm aiming for here is a "custom content" system.


What I do for this is let the server tell the player where to get things if they are needed, and then the client does an http:// file transfer from that location so the server doesn't have to spend time sending that data to the client. Once the server sends the client the location is disconnects the client, and the client acts on that information accordingly. You can have your client remember the last server login attempt and reconnect after the http get file transfers are done.

You'll have to make a system for this.. perhaps any address given you client will expect a "filelist.txt" file to get first then compare that list to existing files and download each one you dont have up to date.

It's also helpful if the media has a standard format to minimize required crc checking I've reduced tiny tanks down to three files ( Map_DP.dat, MAP_SCN.dat, & MAP_PAK.dat)
The _SCN holds the scenery placement data (where what size color ect), The _DP holds special data point data and ambient volume data, and the _PAK file is all the models & textures recreated in my own format and compressed.

I do not have any map specific sounds in the game but one more .dat file for that wouldn't hurt much. The tradeoff is that if I add more models the the map the entire _SCN or _PAK file has to be downloaded depening on if its a placement change or new model added the to the map. But the .DAT files are usually only about 1 to 3 megs in size.

I recommend using the zlibwapi.dll for compressing and super fast crc checks on both banks and files


If you want to see this system in action , just download tiny tanks.. I update the main program , support paks and map data all the time. Clients and servers auto update to the new data.

Last edited 2011


Rroff(Posted 2011) [#6]
I updated my post above a bit btw.

Even for that kinda game I reccomend using UDP, the actual implementation is quite a long subject tho.


Adam Novagen(Posted 2011) [#7]
Thanks Rifraf and Rroff.

Hmm, alright. The URL redirect is the most likely option for me to use, since I'm experimenting to see if I can make a little nicely portable server program so that it can be set up "anywhere by anyone." Oh, just before the cynics around here get started, btw, no I'm not pipe dreaming and trying to make the next WoW or Minecraft. I'm just futzing around for fun with something that I'll pass around to friends for our personal enjoyment.

As for UDP, I noticed shortly after responding to your first post, Rroff, that you mentioned a =>200ms delay just for receiving new TCP streams. With that in mind, then yes, I should definitely get used to UDP. I'm going to need a lot of hand-holding to get started though, since I have absolutely NO idea what I'm doing with UDP, and the documentation for it is... Well, borderline nonexistent. So, here come some MORE questions:

How do I determine the non-dotted integer address of a machine I'm using for a server? My current testing rig is my own computer, which has a web URL provided via DynDNS to avoid problems with my global IP changing from time to time, which it of course does because it's a home internet connection, and security features from the ISP blah blah. How exactly am I supposed to get UDP to connect to something like that?

I gather that a UDP stream is prepared using CreateUDPStream() and then written to with the usual file/stream commands. When exactly should CloseUDPStream be used? Before sending? After? Only at client disconnection?


Yasha(Posted 2011) [#8]
Try taking a look at RottNet: http://www.rottbott-studios.com/rottnet.html

It's a full network library implementing reliable and ordered packets built on top of UDP. I found it very easy to read and understand (except for why on Earth it sends all data as strings, which is unnecessary and wasteful to say the least). Good model to use as a base for building on top of UDP.


Adam Novagen(Posted 2011) [#9]
... God dammit Yasha, you make everything so damn one-stop simple. XD

Thanks a million for that, will check it out soon!


Adam Novagen(Posted 2011) [#10]
Well, RottNet certainly turned out to be God's gift to Blitz networking. While the code within the library itself is so extremely tight that it's a bit beyond my grasp, it's so damn easy to implement that I've already got the server working with a complete self-test procedure and outside connections (had a friend in Ohio test it out). This has made my life a lot easier.

Next step is linking to the file repositories. Since we're talking about downloading valuable game files before the game itself is actually in progress, I would assume this to be an obvious case for TCP usage. I have no idea what to send to the server, though. What does a web browser send out to nab the file dependencies of each webpage it encounters?


Adam Novagen(Posted 2011) [#11]
... DERP, never mind. That was actually incredibly simple. I just modified the OpenTCPStream() example to grab the little german.gif flag icon from this website (top-left corner). Worked like a charm, not an error in sight. Looks like linking to a repo.zip will be simple enough, I just have to tinker with some error-catching code. Blimey, this is exciting! :D


Rroff(Posted 2011) [#12]
Do you have a way to handle zip in b3d? IIRC there are some userlibs for handling compressed files, I wrapped zlib.dll for my (fairly simple) useage (tho this is .gz not .zip).


Adam Novagen(Posted 2011) [#13]
I do indeed; I use the ZIP API that's in the toolbox here. http://blitzbasic.com/toolbox/toolbox.php?tool=171