XNA Creators Club Online
Page 1 of 1 (7 items)
Sort Posts: Previous Next

Lag on system link: network limitations

Last post 9/22/2009 11:31 PM by Wipeless. 6 replies.
  • 9/21/2009 10:33 PM

    Lag on system link: network limitations

    Hello,

      My current setup is just two xboxes connected via system link (wired through a router).  Following the Client-Sever model, one xbox is the host while the other is the client. 

      My client writes out it's current thumbstick positions while the router calculates the position/rotation/etc. and sends it back to the client.

      My client write package consists of:
            xbox trigger values (double: 8 bytes)
            xbox thumbstick values (Vector2: 8 bytes)
            Total: 16 bytes

      My server write package consists of:
            CalculatedPosition (Vector3[numClients]: 12 bytes)
            CalculatedRotation (Vector3[numClients]: 12 bytes)
            CalculatedVelocity (Vector3[numClients]: 12 bytes)
            Total: 36 bytes * numClients.

      When I finally get 4 players connected I'm going to be expecting a server input of 64 bytes and an output of 144 bytes per client.

      However, I've already started noticing some lag with just one-two players (up to about 1 second of lag with just two people; I don't understand why). With a system link setup, I was expecting not having to rely on network prediction to create a seamless connection; especially with such low package sizes being passed around.  Are these package sizes adequate or is there a recommended package size people use for network games? Can there be something wrong with my router?  Does anyone recommend some sort of network monitoring program that would point out what's slowing things down?  I was really hoping to get smoother gameplay with a system link setup.  Thanks!
  • 9/21/2009 10:58 PM In reply to

    Re: Lag on system link: network limitations

    I'm guessing you're using the NetRumble starter kit for this. It only sends out packets every so often and I think this is probably what is causing the lag. You could try sending them out more often. For system link you should be able to do it way more often than XBL.
    You can try wireshark to monitor the network packets sent if you want.

    Pwnage of Empires in Playtest.
  • 9/22/2009 12:03 AM In reply to

    Re: Lag on system link: network limitations

    Impossible to say for sure without seeing more code, but my telepathic powers suggest that perhaps your client machines are just reading one packet per frame, rather than reading in a while (gamer.IsDataAvailable) loop?
    XNA Framework Developer - blog - homepage
  • 9/22/2009 1:25 AM In reply to

    Re: Lag on system link: network limitations

    LocoPuyo:  Thanks for the advice. I've been using the Client-Server example for my network endeavors so far.  The NetRumble example seemed too intimidating but it looks it's time to move on to bigger and better things. I'm looking through it now. When you mean "send more packets" are you suggesting just calling ".sendData" multiple times in one frame?

    Shawn:  Here's some psuedo code of what I'm doing:

    My main network update which occurs in the game update loop.
            NetworkSession networkSession; 
     
            public void UpdateNetwork() 
            { 
                if (networkSession != null
                { 
                    // Read inputs. Send them to the server. 
                    foreach (LocalNetworkGamer gamer in networkSession.LocalGamers) 
                        UpdateLocalGamer(gamer); 

                    if (networkSession.IsHost) 
                            UpdateServer(); 
     
                    // Pump the underlying session object. 
                    networkSession.Update(); 
     
                    // Make sure the session has not ended. 
                    if (networkSession == null
                        return
     
                    // Read any incoming network packets. 
                    foreach (LocalNetworkGamer gamer in networkSession.LocalGamers) 
                    { 
                        if (gamer.IsHost) 
                            ServerReadInputFromClients(gamer); 
                        else 
                            ClientReadGameStateFromServer(gamer); 
                    } 
                } 
            } 

    How I handle client/server input and output:
            int ClientID;  //client ID is determined when player joins lobby. 
     
            //Looking around at the structure of the NetRumble example, I'm  
            //thinking about redoing a few things from my project ;).  Until then,  
            //this shows how I'm storing variables being passed between 
            //the clients and server. 
     
            Vector2[4] leftStick; 
            Vector2[4] rightStick; 
            double[4] leftTrigger; 
            double[4] rightTrigger; 
     
            Vector3[4] handledPos;   
            Vector3[4] handledVelocity_Trans; 
            Vector3[4] handledVelocity_Rot;         
     
            void UpdateLocalGamer(LocalNetworkGamer gamer) 
            { 
                if (!networkSession.IsHost) 
                { 
                    packetWriter.Write(gamer.Id); 
                    packetWriter.Write(ClientID); 
                    packetWriter.Write(leftStick[ClientID]); 
                    packetWriter.Write(rightStick[ClientID]); 
                    packetWriter.Write(leftTrigger[ClientID]); 
                    packetWriter.Write(rightTrigger[ClientID]); 
     
                    // Send our input data to the server. 
                    gamer.SendData(packetWriter, 
                                   SendDataOptions.InOrder, networkSession.Host); 
                } 
            } 
     
            void UpdateServer() 
            { 
                // Loop over all the players in the session, not just the local ones! 
                foreach (NetworkGamer gamer in networkSession.AllGamers) 
                { 
                    // Write the tank state into the output network packet. 
                    packetWriter.Write(gamer.Id); 
                    packetWriter.Write(handledPos[0]); 
                    packetWriter.Write(handledPos[1]); 
                    packetWriter.Write(handledPos[2]); 
                    packetWriter.Write(handledPos[3]); 
                    packetWriter.Write(handledVelocity_Trans[0]); 
                    packetWriter.Write(handledVelocity_Trans[1]); 
                    packetWriter.Write(handledVelocity_Trans[2]); 
                    packetWriter.Write(handledVelocity_Trans[3]); 
                    packetWriter.Write(handledVelocity_Rot[0]); 
                    packetWriter.Write(handledVelocity_Rot[1]); 
                    packetWriter.Write(handledVelocity_Rot[2]); 
                    packetWriter.Write(handledVelocity_Rot[3]); 
                } 
     
                // Send the combined data for all tanks to everyone in the session. 
                LocalNetworkGamer server = (LocalNetworkGamer)networkSession.Host; 
                server.SendData(packetWriter, SendDataOptions.InOrder); 
            } 
     
            void ServerReadInputFromClients(LocalNetworkGamer gamer) 
            { 
                // Keep reading as long as incoming packets are available. 
                while (gamer.IsDataAvailable) 
                { 
                    NetworkGamer sender; 
     
                    // Read a single packet from the network. 
                    gamer.ReceiveData(packetReader, out sender); 
     
                    if (!sender.IsLocal) 
                    { 
                        byte gamerId = packetReader.ReadByte(); 
                        byte gamerClientID = packetReader.ReadByte(); 
                        leftStick[gamerClientID] = packetReader.ReadVector2(); 
                        rightStick[gamerClientID] = packetReader.ReadVector2(); 
                        leftTrigger[gamerClientID] = packetReader.ReadDouble(); 
                        rightTrigger[gamerClientID] = packetReader.ReadDouble(); 
                    } 
                } 
            } 
     
            void ClientReadGameStateFromServer(LocalNetworkGamer gamer) 
            { 
                while (gamer.IsDataAvailable) 
                { 
                    NetworkGamer sender; 
     
                    // Read a single packet from the network. 
                    gamer.ReceiveData(packetReader, out sender); 
     
                    while (packetReader.Position < packetReader.Length) 
                    { 
                        // Read the state of one tank from the network packet. 
                        byte gamerId = packetReader.ReadByte(); 
                        handledPos[0] = packetReader.ReadVector3(); 
                        handledPos[1] = packetReader.ReadVector3(); 
                        handledPos[2] = packetReader.ReadVector3(); 
                        handledPos[3] = packetReader.ReadVector3(); 
                        handledVelocity_Trans[0] = packetReader.ReadVector3(); 
                        handledVelocity_Trans[1] = packetReader.ReadVector3(); 
                        handledVelocity_Trans[2] = packetReader.ReadVector3(); 
                        handledVelocity_Trans[3] = packetReader.ReadVector3(); 
                        handledVelocity_Rot[0] = packetReader.ReadVector3(); 
                        handledVelocity_Rot[1] = packetReader.ReadVector3(); 
                        handledVelocity_Rot[2] = packetReader.ReadVector3(); 
                        handledVelocity_Rot[3] = packetReader.ReadVector3(); 
                    } 
                } 
            } 

    So, with my limited networking experience, it seems like the clients are receiving the packets sent from the server.  While debugging my project, I can see the server reading client inputs with no problem.  It's just waiting for the client to receive info from the server is what's causing the lag.  When I hook up another client (using my PC: 2 clients and 1 host) things get really choppy.  However I notice Client A updating normally (with minor pangs of lag) while Client B takes about 10 seconds or more to update the position sent from the server.  It gets so bad that I just end up watching what Client B is doing from Client A's screen.  It's as if one client is getting priority over the other in regards to receiving updated positions from the server. Anyway,  please let me know if you have any ideas.  Until then, I'll look over the NetRumble code.

  • 9/22/2009 7:55 PM In reply to

    Re: Lag on system link: network limitations

    In t he netrumble it doesn't send out packets to every player every frame. it finds out how many max players there can be, which is set to 16, then staggers when it sends packets out every 16 frames.

    I'm no expert to how it works, but just a guess is that the framerate may be slower on one and its getting way more packets than it needs every frame and can't handle it. Falling behind and processing packets that are older and older.
    Pwnage of Empires in Playtest.
  • 9/22/2009 8:17 PM In reply to

    Re: Lag on system link: network limitations

    Note that "packet" or "message" generally is not the same thing as UDP datagram. The network framework will generally pack multiple messages into a single UDP datagram. You really need to drain the incoming message queue fully each time through your main loop.
    Jon Watte, Direct3D MVP
    Tweets, occasionally
    kW X-port 3ds Max .X exporter
    kW Animation source code
  • 9/22/2009 11:31 PM In reply to

    Re: Lag on system link: network limitations

    LocoPuyo:
    I'm no expert to how it works, but just a guess is that the framerate may be slower on one and its getting way more packets than it needs every frame and can't handle it. Falling behind and processing packets that are older and older.


    jwatte:
    Note that "packet" or "message" generally is not the same thing as UDP datagram. The network framework will generally pack multiple messages into a single UDP datagram. You really need to drain the incoming message queue fully each time through your main loop.


    So, when you execute:
        packetWriter.Write(foo);
        LocalNetworkGamer.SendData(packetWriter, SendDataOptions.InOrder);

    This creates a "packet" or "message" correct? 

    The moment I try to send multiple packets (if I where to put the above code in a for loop) those "packets" are streamed out in a single UDP datagram? 

    In my case, I'm noticing problems with the server writing out to clients.  To prevent sending out more packets than the clients to handle, are you talking about using the .Flush() function of a packetWriter in my server main loop?

    Also, when I debug my program, should I not be combining different machines for network tests?  I have one PC and 2 xboxes available for my network tests.  When I have the host as the PC and the xboxes as clients, both clients run sluggishly (one being more slow than the other).  However, when I have one xbox set as the host and the other xbox and PC as clients, the PC runs fine while the xbox is still quite sluggish.  Should I stick with only running one type of machine for networking tests?  I really thought there would be no problems with a system link.
Page 1 of 1 (7 items) Previous Next