Search code examples
c#xnaudpclient

UDPClient.Receive() stops any code from running


I'm trying to create a simple game using the XNA Framework. I'm starting to implement multiplayer over LAN. Everything has been going well but now I'm running into a problem with UDPClient.Receive.

When the server is running, it is supposed to have two listeners(using UDPClient.Receive), on different ports. One listener is waiting for any incoming connection requests for people who want to join the game and respond accordingly. The other listens for constant updates on the player's positions so it can keep all players' views synchronised. The problem is that I don't know how to code in the first listener.

When the listener for connection request starts, all the code freezes, and it doesn't start until that listener will receive something. How would I code it so it is just running in the background?

Here is my code for the connection listener:

public class Connect
{
    public static void WaitForConnections()
    {
        UdpClient udpc2 = new UdpClient(2054);
        IPEndPoint ep = null;

        Random rnd = new Random();

        Console.WriteLine("Waiting for connections...");
        byte[] joinrequest = udpc2.Receive(ref ep);
        if (Encoding.ASCII.GetString(joinrequest) == "join")
        {
            Console.WriteLine("Attempting to join");
            if (Server.ConnectedPlayers.Count < Server.MaxPlayers)
            {
                byte[] newShooter = DataControls.ClassToByteArray(new ShooterObject(Server.ConnectedPlayers.Count + 1, new Vector2(((Server.ConnectedPlayers.Count + 1) * 100) + 22, 70), new byte[3] { (byte)rnd.Next(255), (byte)rnd.Next(255), (byte)rnd.Next(255) }));
                udpc2.Send(newShooter, newShooter.Length, ep);
                Console.WriteLine("Joined successfully");
            }
            else
            {
                byte[] error = Encoding.ASCII.GetBytes("full");
                udpc2.Send(error, error.Length, ep);
                Console.WriteLine("Too many players");
            }
        }
    }
}

Solution

  • You need to use a background worker thread or equivalent (look at Task and threads generally) but to help you get going in basic full example:

    using System;
    using System.ComponentModel;
    using System.Threading;
    
    namespace ConsoleApplication1
    {
        internal class Program
        {
            private static void Main()
            {
                // Create our listener and start listening...
                var sammpleListener = new SampleListener();
                sammpleListener.StartListening();
    
                // Run forever...
                Console.WriteLine("Waiting for players to join...");
                Console.WriteLine("Press Ctrl+C to stop!");
                for (var counter = 1;; counter++)
                {
                    Console.WriteLine("Main thread working: {0}...", counter);
                    Thread.Sleep(200);
                }
            }
    
            internal class SampleListener
            {
                private readonly BackgroundWorker _udpWaitForPlayer;
    
                public SampleListener()
                {
                    _udpWaitForPlayer = new BackgroundWorker();
                    _udpWaitForPlayer.DoWork += _udpWaitForPlayer_DoWork;
                }
    
                public void StartListening()
                {
                    _udpWaitForPlayer.RunWorkerAsync();
                }
    
                private void _udpWaitForPlayer_DoWork(object sender, DoWorkEventArgs e)
                {
                    const int junkSample = 10;
                    for (var i = 1; i <= junkSample; i++)
                    {
                        // Notice how this doesn't make the main thread sleep / hang...
                        Console.WriteLine("Background worker working: {0} of {1}...", i, junkSample);
                        Thread.Sleep(1000);
                    }
                    Console.WriteLine("Background worker: Finished!");
                }
            }
        }
    }