This is the next post in my Fondusi’s Development Blog series. Click here to check out week 5 or start at the beginning.

Week 6 – September 5th – September 11th

This week we spent some time doing little things – fixing bugs, changing how things look, etc. We also started work on the networking code which is going to be what I’m going to talk about here.

A TCP Network Server in C#

My first step was to develop a way for multiple clients to connect with the server. Before starting this, I hadn’t really done much with threading or sockets in C#. However, I knew the idea behind threading, and I’d used TCP sockets in VB6 (for the old version of Fondusi’s).

If you’ve never used sockets in VB6, it works similarly to Async sockets in C#. Basically, you would add a socket object to a form and whenever it received a connection or data, a callback event would be fired. Trying to *easily* translate this to C# was proving difficult, however. Not only because of the differences in the languages, but also because the new server is a console application and the old one was windows forms.

I finally settled on creating a threaded server where there was one listening socket which, upon connection, spawned a receiving thread for the connected socket. When the socket disconnects, the receive thread function throws an error and the thread ends.

Now, I haven’t tested this with many connections yet, since I don’t yet have working client code for players (we’re only doing the map editor, remember). But, with the number of connections in tests I’ve done, everything works fine.

Anyways, enough with my background story, let’s get to the meat. Mmmm delicious meat. Here’s how the server works.

Listening for Connections

First things first, we need to set up our listening socket and thread. Create a new class (I called mine “NetServer”) and add these instance variables:

The next thing we need to do is create a method that will listen for and accept connections on the listener thread.

This method begins by binding the listening socket to any address on the host machine on port 55555. The next line tells it to start listening with a connection queue of 30. This means that if multiple connections come in at the same time, they will be queued (to a maximum queue length of 30) until Accept() is called. After that, we output to the console that we’re listening and on what IP/port. We then begin our accept connection loop.

The boolean variable _stopListening allows us to exit the loop later on. Within the loop, we see that the return value of _listenSocket.Accept() is passed to the AcceptConnection function. One thing I want to note here is that the Accept function is “blocking”, which means that the function blocks the calling thread and waits to return until it has something to return. This means that, if we ran it on the main thread, it would stop the main thread’s execution until someone tried to make a connection. This is why we have to run the listener on it’s own thread.

Accepting Connections

Now, you’re probably wondering what the deal is with the AcceptConnection method. (Note: If you’re not wondering that, you should be!) _listenSocket.Accept() returns the newly connected socket and that gets passed into the AcceptConnection method. AcceptConnection does a few things for us. It:

  • Sets NoDelay for the TCP socket so that the packets don’t get buffered before sending.
  • Finds an open slot for the connection.
  • Adds the connection into the slot or sends an alert to the client saying there are no open slots.
  • Creates and starts the receiver thread for that client.

You could put all the code in the Listen method, but for the sake of readability and explanation, I decided to split it up. So here’s the code:

I’ve added comments to the code and I think it’s pretty self-explanatory so I won’t describe it any more.

Time-out

This post has become longer than I was expecting and there’s a lot more left to do discussing the ReceiveData function. So, I’ve decided to split that into a separate post. However, I do want to finish off some stuff here first.

Time-in – Initializing the Listening Thread

If you’re sharp, you may have noticed that the listening thread is never created or started. To set up the listening thread, add these lines to your class’s constructor:

This is basically just telling the listening thread to execute the Listen method when _listeningThread.Start() is called. If you’re wondering what the IsBackground property does, it tells the CLR that we don’t want the application to wait for this thread to finish if it’s trying to terminate (close). The actual description from MSDN is this:

Background threads are identical to foreground threads, except that background threads do not prevent a process from terminating. Once all foreground threads belonging to a process have terminated, the common language runtime ends the process. Any remaining background threads are stopped and do not complete.

Controlling the Server

The last bit is the two control functions for our NetServer class. These allow the server to be started and stopped.

Again, the code here is pretty self-explanatory (especially with comments) so I’m not going to delve into it. Check out Part 2 (when I post it) for the ReceiveData function and explanation.

The Rest

Finally, here’s the change log for the rest of the stuff we did this week:

  • Fixed bug with players appering to be on the wrong map/layer
  • Fixed a bug switching player layers in the entry behaviours
  • Added box texture to tile engine
  • Fixed drawing of player names (made them centred)
  • Added player hp bar
  • Fixed a bug with region editing
  • Added player stats
  • Updated tile entry damage, heal and kill behaviours
  • Removed error thrown when no maps found
  • Added more to Animation Form and added button to open animation form on Controls Form
  • Changed size of player HP bar
  • Set player health by default
  • Added Resource object to be used for text and icons and the such
  • Added icons for the map edit controls (Tile Draw, etc)
  • Resized and moved around map edit controls
  • Fixed bug with tile editor not reseting to Tile Draw control, and drawing a 2×2 tile when nothing is selected
  • Added tool tips and string resources for the Tile Edit [radio]buttons
  • Removed ImageComboBox
  • Added ImageListBox
  • Have hard coded tiles adding to the Animated Tile image stack, very close to finishing the create/edit form!
  • Added map server project with basic threading in the console
  • Added the ability to remove layer switching entry behaviours by right clicking
  • Show arrows on the map for layer change tiles while the layer change tab is active
  • Added players array and server info constants to GameObjects
  • Added basic Player class
  • Renamed network thread to server thread
  • Created a socket list class
  • Added some classes/code for testing the map server
  • Got some basic socket connections working