Search Unity

Showcase LiteNetLib - another reliable udp library.

Discussion in 'Multiplayer' started by RevenantX, Jun 30, 2016.

  1. GerardQ

    GerardQ

    Joined:
    Oct 15, 2011
    Posts:
    68
    Hi, @RevenantX

    Your LiteNetLib looks absolutely awesome. My question is if you expect it to be affected by Unity's decision to deprecate and replace UNet?
     
  2. GerardQ

    GerardQ

    Joined:
    Oct 15, 2011
    Posts:
    68
    Hi, @RevenantX and all:

    I was excited to find this forum thread. Back in 2016 I published a Unity 4 mobile game (https://teamthunder.kuduq.com) featuring 2-player P2P over LAN that used UDP from System.Net and System.Net.Sockets to make a connection automatically. From there it then dropped UDP and used (now deprecated) Unity 4's standard networking with NetworkView Components and RPC calls to synchronize moving transforms on the client and server devices. I must admit I'm not super experienced with network programming, but got it working by hook and by crook.

    This year I decided to create a new game with 2-player P2P, but of course ran into the problem that the (newer) Unet networking has been deprecated with no replacement before I even started. So, after looking around at all kinds of 3rd party packages including the Asset Store, I found this little gem. I see LiteNetLib even supports UDP NAT hole-punching, which is awesome and I'm hoping I can get that working too.

    Now, I'm seeking some guidance on building:
    - the LAN client and server, and
    - the NAT punchthrough solution with client, host, and NAT facilitator.

    Any help, guidance, code samples much appreciated.

    Also, what do you experts recommend platform wise for implementing the NAT facilitating server? My websites are through a paid web hosting service that uses CPanel on linux servers, so I was wondering if anyone has tried an ASP.NET implementation, or what would you recommend?

    Gerard
     
    Last edited: May 29, 2020
  3. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    @GerardQ Hi! There is all examples at GitHub page. Check README file you will find all things you need (including "nat punch" server example that can be run on .netcore on Linux)
     
  4. GerardQ

    GerardQ

    Joined:
    Oct 15, 2011
    Posts:
    68
    @RevenantX Hello!

    Thanks so much for replying.

    Absolutely. I've already downloaded everything I can find and I'm trying to understand how to use it. :) The features in the README file is what brought me to here. It's great stuff. I think you're a genius. I hope I can learn to use it properly.

    Do you mean "HolePunchServerTest.cs"?

    I did a little digging based on what you say here. Here are a few questions:

    - To run on Linux I have to get .NET CORE installed on Linux, correct? If so, this shouldn't be a problem on my personal laptop that runs Ubuntu Server, although it's still 16.04 LTS. (I use MAC and Linux, but not Windows).

    - To get it on my paid Hosting Service, (which is a linux-based platform using cpanel,) might be a little bit more difficult because I would probably need access to the core, but hopefully that can be done. Have you tried that?

    - Trying to build a server for multiplayer on a hosted cpanel platform will probably not work, because I suspect it will be too slow. However, a NAT punch facilitating server is probably doable. Your comments?

    - Also, have you attempted using ASP.NET for this? I suspect ASP.NET will be the easiest way to build an interface for the NAT punch server and then running the server itself straight using .netcore. Comments?
     
    Last edited: May 31, 2020
  5. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    @GerardQ .netcore on linux is very easy to setup. ASP.NET for "hole" punching is overkill. There is "HolePunchServerTest" with example simple implementation of hole punch on LiteNetLib that will work on clean .netcore (version 2.1 at least)
     
  6. GerardQ

    GerardQ

    Joined:
    Oct 15, 2011
    Posts:
    68
    Thanks, great advice.

    I've installed the .NET CORE under Ubuntu and now figuring out how to run your samples, because it's still complaining when I try.
     
  7. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    Changed donation link to other system. Should work now! :)
     
  8. scheichs

    scheichs

    Joined:
    Sep 7, 2013
    Posts:
    77
    Yep, works now!
     
  9. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
  10. scheichs

    scheichs

    Joined:
    Sep 7, 2013
    Posts:
    77
    No! I thank YOU! Best man! :)
     
  11. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    LiteNetLib updated to 0.9.3.1
    https://github.com/RevenantX/LiteNetLib/releases/tag/v0.9.3.1
    (changes since 0.9.3)
    • Fix possible infinite(or very long) loop on high-load in PollEvents()
    (changes since 0.9.2.2)
    • Protocol increased to 11
    • Added support of List<T> for NetSerializer/NetPacketProcessor for custom types (nested types from wiki)
    • Fixed unsynced connect
    • Added dual mode for IPv6 (one socket used for IPv4 and IPv6 - so you get less "receive" threads, but this doesn't tested on any platforms except Win/Linux)
    • Improved hole punching code
    • Fixed simultaneous P2P connection (you will get disconnect from one side with DisconnecReason.PeerToPeerConnection)
    • Improved Unity iOS reconnect hack
    • Added fix for Nintendo Switch
    • Moved contents of NetExceptions.cs to NetDebug.cs so NetExceptions.cs is deleted
     
    -chris, JosephMA007, scheichs and 2 others like this.
  12. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    63
    Hello @RevenantX. I've started using LiteNetLib with great success so far, but got stuck at this: I need to send a packet unreliably, but it's size exceeds MTU - so LiteNetLib throws an exception and refuses to send it unreliably. What is the cheapest possible way of sending an oversized packet? And I prefer to loose the packet if just one part is lost, i.e. I don't need reliability.
     
  13. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    https://github.com/RevenantX/LiteNetLib/issues/357#issuecomment-608557088
     
  14. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    63
    Thank you. I realize that I can split my data myself. I just looked through LiteNetLib source and have seen fragment splitting code is there already. Instead of writing similar code myself on top of LiteNetLib I'd very much prefer to use it's built-in packet fragmentation mechanism. Instead of just restricting unreliable packets in size, why not split them and simply send through unreliable queue? In case they arrive in order they will be rebuilt on the receiving side, otherwise the whole packet can be considered lost
     
  15. manutoo

    manutoo

    Joined:
    Jul 13, 2010
    Posts:
    523
    @RevenantX , do you know if LiteNetLib could work on PS4 & XBox ? Do you know if anyone tried it on such consoles ?

    Thanks in advance for your answer ! :)
     
  16. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    @manutoo i used it in PS4 game prototype. But this game never released. It should work because it doesn't use any platrform specific things.
     
    manutoo likes this.
  17. garrido86

    garrido86

    Joined:
    Dec 17, 2013
    Posts:
    233
    I'm experiencing the issue where I can get this to work between Android and a Windows 10 PC, but only when the Firewall is disabled. I also tried connection between two Android devices that doesn't work as well, what do I need to do get it working in local wifi? I should note that I skip the part about broadcasting or sending unconnect messages, instead the host displays its IP adress and desired port as a QR Code which is scanned by the client which in turn immediately calls the connect function.

    //edit
    I got it now working between android devices! I just had to use port "10515" which is the same you have been using in your game sample project. I have been previously using port "9050", I suppose that port is not allowed for peer-to-peer? Would love to hear which ports are recommended to use :)
     
    Last edited: Jan 21, 2021
  18. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    63
    Hello. Is there plans to make LiteNetLib only depend on .Net Standard? I noticed there is some .Net Standard-compatible LiteNetLib fork on NuGet, but it seems to be only v.0.8.0. How about v.0.9.4?
     
  19. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    LiteNetLib is available for .NET Standard 2.0 and also for .net core.
    From main github readme - "Lite reliable UDP library for .NET Framework 3.5, Mono, .NET Core 2.1, .NET Standard 2.0."
     
  20. AcIdSaMa

    AcIdSaMa

    Joined:
    Dec 5, 2012
    Posts:
    19
    I posted an issue about this on the github but haven't gotten an answer yet.

    Trying to set up Nat Traversal but when I try to Send the nat intro I get this error message.

    Tried this on a fresh project I'm using 2020.2.4 if that makes a different or not.

    upload_2021-3-9_13-9-2.png
     
  21. moognsszy

    moognsszy

    Joined:
    Nov 4, 2018
    Posts:
    3
    Hello there! RevenantX, I'm trying this library, there is a problem, I need to disable IPV6, I tried (public IPv6Mode IPv6Enabled = IPv6Mode.Disabled;) but the server does not work. I use DLL, please tell me what to do, thank you!
    Code (CSharp):
    1. using System;
    2. using System.Net;
    3. using System.Net.Sockets;
    4. using UnityEngine;
    5. using LiteNetLib;
    6. using LiteNetLib.Utils;
    7.  
    8. public class GameServer : MonoBehaviour, INetEventListener, INetLogger
    9. {
    10.     private NetManager _netServer;
    11.     private NetPeer _ourPeer;
    12.     private NetDataWriter _dataWriter;
    13.  
    14.     [SerializeField] private GameObject _serverBall;
    15.  
    16.     void Start()
    17.     {
    18.         NetDebug.Logger = this;
    19.         _dataWriter = new NetDataWriter();
    20.         _netServer = new NetManager(this);
    21.         _netServer.Start(5000);
    22.         _netServer.BroadcastReceiveEnabled = true;
    23.         _netServer.UpdateTime = 15;
    24.     }
    25.  
    26.     void Update()
    27.     {
    28.         _netServer.PollEvents();
    29.     }
    30.  
    31.     void FixedUpdate()
    32.     {
    33.         if (_ourPeer != null)
    34.         {
    35.             _serverBall.transform.Translate(1f * Time.fixedDeltaTime, 0f, 0f);
    36.             _dataWriter.Reset();
    37.             _dataWriter.Put(_serverBall.transform.position.x);
    38.             _ourPeer.Send(_dataWriter, DeliveryMethod.Sequenced);
    39.         }
    40.     }
    41.  
    42.     void OnDestroy()
    43.     {
    44.         NetDebug.Logger = null;
    45.         if (_netServer != null)
    46.             _netServer.Stop();
    47.     }
    48.  
    49.     public void OnPeerConnected(NetPeer peer)
    50.     {
    51.         Debug.Log("[SERVER] We have new peer " + peer.EndPoint);
    52.         _ourPeer = peer;
    53.     }
    54.  
    55.     public void OnNetworkError(IPEndPoint endPoint, SocketError socketErrorCode)
    56.     {
    57.         Debug.Log("[SERVER] error " + socketErrorCode);
    58.     }
    59.  
    60.     public void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader,
    61.         UnconnectedMessageType messageType)
    62.     {
    63.         if (messageType == UnconnectedMessageType.Broadcast)
    64.         {
    65.             Debug.Log("[SERVER] Received discovery request. Send discovery response");
    66.             NetDataWriter resp = new NetDataWriter();
    67.             resp.Put(1);
    68.             _netServer.SendUnconnectedMessage(resp, remoteEndPoint);
    69.         }
    70.     }
    71.  
    72.     public void OnNetworkLatencyUpdate(NetPeer peer, int latency)
    73.     {
    74.     }
    75.  
    76.     public void OnConnectionRequest(ConnectionRequest request)
    77.     {
    78.         request.AcceptIfKey("sample_app");
    79.     }
    80.  
    81.     public void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo)
    82.     {
    83.         Debug.Log("[SERVER] peer disconnected " + peer.EndPoint + ", info: " + disconnectInfo.Reason);
    84.         if (peer == _ourPeer)
    85.             _ourPeer = null;
    86.     }
    87.  
    88.     public void OnNetworkReceive(NetPeer peer, NetPacketReader reader, DeliveryMethod deliveryMethod)
    89.     {
    90.     }
    91.  
    92.     public void WriteNet(NetLogLevel level, string str, params object[] args)
    93.     {
    94.         Debug.LogFormat(str, args);
    95.     }
    96. }
     
  22. moognsszy

    moognsszy

    Joined:
    Nov 4, 2018
    Posts:
    3
    The server script seems to be unable to choose IPV4 or IPV6, I don’t know what I did wrong
     
  23. moognsszy

    moognsszy

    Joined:
    Nov 4, 2018
    Posts:
    3
    Hello there! RevenantX, I have solved the problem mentioned above, thanks! !
     
  24. SocialArenaPR

    SocialArenaPR

    Joined:
    Sep 26, 2016
    Posts:
    77
    I'm using this as the basis for my Multiplayer/MMO Framework. Back in 2014 or so I started a framework called UniVerse which at the time I was using Lidgren for the networking. I am now updating it and creating UniVerse 2 which uses this for the networking.
     
  25. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    63
    Hi there. Got a question: how do I make sure that all packets have been sent before calling NetManager.Stop()? I tried calling NetManager.TriggerUpdate() immediately before calling Stop(), but that doesn't work as far as I can tell. Is there a way to ensure processing of all outgoing packets before stopping net manager?
     
  26. Punfish

    Punfish

    Joined:
    Dec 7, 2014
    Posts:
    401
    I don't recall off the top of my head the name but there's an option when disconnecting the client to have it send packets in the queue first. Although admittedly, this has not worked for me on several occasions. I'm unsure if LNL is simply not delivering packets before socket is closed or if close packet is maybe read before the rest.

    Edit: I thought there was a specific disconnect which would flush the queue first, and I still believe there is but I cannot find it.
    However, you can simply add the connection Id to a queue and then disconnect them next tick.
     
    Last edited: Apr 1, 2022
  27. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    63
    Not sure I understand what "next tick" means. I need to stop the NetManager, but make sure that all packets have been sent. By "next tick" do you mean a call to NetManager.PollEvents()? If so, then it's not what I need - it will only process incoming packets, but what I need is to finish processing outgoing packets, which, judjing from source code, happens on a separate thread.
     
  28. SocialArenaPR

    SocialArenaPR

    Joined:
    Sep 26, 2016
    Posts:
    77
    Is there any way to get the size of a packet before sending it? I'd like to get an idea on how large my packets are that I am sending.
     
  29. -chris

    -chris

    Joined:
    Mar 1, 2012
    Posts:
    99
    Could probably check NetDataWriter.Length? Or NetDataWriter.Data.Length?
     
  30. nemanjab

    nemanjab

    Joined:
    Jan 10, 2019
    Posts:
    12
    I want to simulate latency, but it's not working for me. Can someone help?

    upload_2023-7-14_16-43-57.png upload_2023-7-14_16-44-53.png

    Also, when simulating latency with Clumsy, first second I get ping 0 and then it starts receiving latency.
    And when I set Clumsy to 400ms it starts receiving UDP packet after 5 seconds, 300ms and below works like a charm.
     
  31. IceBeamGames

    IceBeamGames

    Joined:
    Feb 9, 2014
    Posts:
    170
    Hey @RevenantX

    Our game is using a fairly old (late 2021) version of litenetlib to connect peers together for a multiplayer match. It seems that, under certain conditions, the server receives OnNatIntroductionRequest both internal and externally and then adds two separate peers, even though they are the same client.

    I was wondering whether its the responsibility of LiteNetLib to filter out these duplicate requests, or something our code should handle. Also, whether this is a known issue (and fixed) issue?

    I tried updating to the latest LiteNetLib but unfortunetely the api seems to have changed, and the code doesn't compile. I didn't originally write the netcode, so won't be able to easily repair it.

    I was looking for a recomendation of how to handle this?
     
  32. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    You should check this on your side by assigning to peers some type of "tokens" to detect that this is same peer and use internaladdress to connect, otherwise if "tokens" isn't equal - this is different players situation
     
  33. IceBeamGames

    IceBeamGames

    Joined:
    Feb 9, 2014
    Posts:
    170
    Thanks for rthe response @RevenantX. I have a solution I am trying from your suggestion.

    I am also seeing some players having issues connecting using the NatPunch. You mention on earlier in this thread that sometimes it can fail with "symmetric NAT" and on your github suggest that, if that happens, you can "easily create a UDP tunnel".

    Do you have an example of creating a UDP tunnel with LiteNetLib?