Skip to main content

Building a networked, multiplayer .NET Core console application

I felt a desire to do something I hadn't tried yet, and that was to make a multiplayer game over the network within a .NET Core console application. Because - why not? Programming allows us to create anything we can think of. Let's have a look at making our game, Packet Battle!

Main screen in Packet Battle
Packet Battle!

Overview

The format of this article is we will approach different aspects we need to solve in order to make Packet Battle, and at the very end I'll share the entire source you can run and play Packet Battle with your friends.

Playing video games with friends (credit University of Wisconsin Madison)
Playing video games with friends

You likely won't have as much fun as these people, but games are as much as you put into them. Let's begin.

Defining "server" and "client"

Before we go further, it is essential to understand the difference between a server and a client. In the terms of a game, each player is typically a client that joins a server that hosts multiple clients. Examples of these types of games are MMOs, team-based shooters, or medieval simulators. The server is the mediator of all of the clients within the game.

The type of architecture we are building for Packet Battle is more similar to a P2P (peer-to-peer) architecture where each client also acts like a server and has equal control over the control over the game as a whole.

P2P architecture (credit to gamedevelopment.tutsplus.com)
The P2P architecture

Yes - each user who wants to play Packet Battle will be running the exact same code. This is similar architecture to P2P applications (including ones that got sued for copyright infringement; but we aren't going to get sued for this game do not worry).

Listening for network requests

The heart of this game is communication, specifically TCP communication. We can't have a network game without communicating to the other players, and the way we are going to do that is through TCP.

We could choose to use UDP, but we are not guaranteed our communication will reach the other person. We'll discuss the difference between TCP and UDP in a future post.

Taken from the official documentation, the simplest code we need to write in our console app to create a "server" is to use the TcpListener. Below is some sample code that does that:

// Create the TcpListener
int port = 6000;
string myIP = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0].ToString();
TcpListener listener = new TcpListener(IPAddress.Parse(myIP), port);

try
{
    // Listen for connections
    listener.Start();

    // Save information sent to our server
    string message = string.Empty;

    // AcceptTcpClient is a blocking method call
    using (TcpClient client = listener.AcceptTcpClient())
    {
        using (NetworkStream ns = client.GetStream())
        {
            // Create a buffer and read the message sent to our server
            byte[] buffer = new byte[1024];
            int bytesRead = ns.Read(buffer, 0, buffer.Length);

            message = Encoding.ASCII.GetString(buffer, 0, bytesRead);
        }
    }
}
catch (Exception ex)
{
    // Print errors
    Console.WriteLine(ex);
}
finally
{
    // Stop listening for connections
    listener.Stop();
}

This code is the bare-minimum you need in order to create a local server that listens for connections on a given port, and saves information that is sent to it. A few things we should note however - AcceptTcpClient is a blocking call, which means that the program flow will stop once we reach this code and not continue executing until we accept a given connection on our IP and port we've assigned to the TcpListener.

Once we have accepted a connection, a TcpClient is created. We get the [network] stream from the TcpClient and read data from it, converting the bytes we received into a string. Finally, we stop listening for connections and end the program.

Sending data

In order for us to have a true multiplayer experience, you need to be able to play with other players. In our example, this requires us to send data to another user, and can be done with the following code below:

// Sending data to a server
string theirIP = "54.11.182.14";
int theirPort = 6005;

string data = "my data";
char[] charArray = data.ToCharArray();
using (TcpClient client = new TcpClient(theirIP, theirPort))
{
    using (NetworkStream ns = client.GetStream())
    {
        byte[] byteMessage = Encoding.ASCII.GetBytes(charArray);
        ns.Write(byteMessage, 0, byteMessage.Length);
    }
}  

We create a new TcpClient with the user's IP and port, reference the [network] stream and send bytes to the stream. These bytes get picked up on the user's computer - and they react to however they need to with the data. Which reminds me...

The contract

How will the computers communicate with each other? It depends. The nature of the "communication" depends on the game. Will one client request if a server is available, and if the server is available, what types of messages will the server tell the client? If the client sees the server is available, how will it communicate back to the server that the client is ready? How will gameplay continue after this?

In order to answer these questions, it is essential to know how the game of Packet Battle will play, and for that I turn your attention to this high-render image of our gameplay:

How the game flows
Game flow

Player 2 will choose a letter. This letter will be sent to Player 1 with 4 other random letters. Player 1 needs to choose what letter Player 2 picked. Depending if Player 1 chose correctly, they may get one point (otherwise nothing). Scores will be updated, and the same steps are played out in the opposite way.

These steps will continue looping until one player has 3 points, at which point the game will end.

Gameplay

See a sample of the new title sure to WOW all your friends and family in 2018. Packet Battle!!

Packet Battle gif
Actual game engine footage 

Note - if you do try to run two copies of the application locally, be sure to change the port on each instance to something different. I used 6000 and 6001 in the footage above but you can use others if those are being used for some reason.

Source

You can pull all the source for the project here.

Take some extra time and look at how we used C# extension methods, interpolated stringsusing static directive, Fisher-Yates algorithm and the C# out keyword. For extra homework, you can work to add the following features into Packet Battle that are not currently implemented:

  1. The ability to pass in a port value that your application uses (that is not hardcoded)
  2. Closing the TcpListener without using alt + f4 (maybe this?)
  3. Selecting the IP of the server from a list that is populated when searching for the game as a client instead of typing it in manually (this might be a good place to start)
  4. Allow the user to enter in an IPv4 or IPv6 address

Comments

  1. I was diagnosed as HEPATITIS B carrier in 2013 with fibrosis of the
    liver already present. I started on antiviral medications which
    reduced the viral load initially. After a couple of years the virus
    became resistant. I started on HEPATITIS B Herbal treatment from
    ULTIMATE LIFE CLINIC (www.ultimatelifeclinic.com) in March, 2020. Their
    treatment totally reversed the virus. I did another blood test after
    the 6 months long treatment and tested negative to the virus. Amazing
    treatment! This treatment is a breakthrough for all HBV carriers.

    ReplyDelete

Post a Comment

Popular posts from this blog

UI redesigns are mostly a waste of time

To preface the article, I primarily work on, and prefer, back-end code. I've been involved in both web and software development for over 4 years now and worked with many front-end and back-end frameworks. New Twitter UI Before all of the UI designers that read this go out and riot and champion against me for saying UI redesigns are a waste of time, let me say that I do value design . I think at the bare minimum, a product or website needs to be usable , and if you possess a good eye and steady hand , you should feel compelled to create something that looks pleasing. David Just stop redesigning the UI all the time . UI redesigns, in my opinion, are a waste of time 95% of the time. Let me explain further. No one cares Come see our fresh new look ! What about our new  material design , come see! I'm sorry, but besides fixing the UI where it impacts the usability of your application, no one is raving about how a redesign makes the application any better.

[Fix] - ASUS PCE-AC68 adapter (no internet)

There seem to be a lot of problems with this adapter, even with such strong performance . Why so many issues? I'm not quite sure, but I needed to find a fix because I kept on losing wifi. The ASUS PCE-AC68 The fix Keeping it short - this is how I fixed the issue: Downloaded the driver for my OS from ASUS's support page -  https://www.asus.com/us/Networking/PCEAC68/HelpDesk_Download/ (in my case it was Windows 10 64-bit). Open Device Manager by holding the Windows key and pressing R, then typing "devmgmt.msc" and hitting Enter. (Don't worry, this isn't a scam . We are simply opening Window's Device Manager through the Microsoft Management Console snap-in .) Navigate to the yellow warning sign sitting under Network adapters and right click it. Select Update driver . Select Browse my computer for driver software  and choose the following path of the OS that you have installed on your computer. (The path for the driver on my computer was C

Logging into a website with Powershell

Powershell is great, and it's lately been my go-to shell while I'm working on Windows. Sorry command prompt I really don't do a lot of work in the shell, but I do like to play with low-level interfaces from time to time. The article is about Linux shells, but goes into good explanation about what a shell is if you don't know. Log into a website Today, I wanted to do something that I have never really tried before and that is logging into a website using Powershell . The concepts behind this are quite simple really, as Powershell has support to send HTTP requests  and that's usually all we need, unless the server has CSRF protections in place (which it should). We are going to attempt  to log in to my favorite website for buying socks, Absolute Socks : Is that a turkey?! In order to do that, we need to have a login. So if you don't already have an account on www.absolutesocks.com , go make one now. Viewing the login request On websites,