Lidgren.Network – an introduction to networking in C# games

http://genericgamedev.com/tutorials/lidgren-network-an-introduction-to-networking-in-csharp-games/

Ten or so days ago I started working on a new project – a game prototype currently called Syzygy. You can find the code for the entire project on GitHub, so feel free to take a look!

The game will have, and is from the start built around multiplayer gameplay. Since I want to get to work on the gameplay as quickly as possible, I did not want to spend any time writing my own networking library.

When searching online for what other people are using for their C# multiplayer games I came across Lidgren.Network by Michael Lidgren. The library had been used in another project I was part of several years ago, and I did not find any obviously better alternatives, so I decided to give it a try.

Unfortunately, the library’s documentation is scarce and partly out of date. The same goes for useful examples, or I am really bad at finding them.

Last week I taught myself the basics of the Lidgren.Network, while adding a connection and lobby system to Syzygy. Today I would like to share what I have learned to hopefully help others that are looking into using the library.

In this tutorial I will:

  • go over the most important types of the library;
  • explain how to set up a simple connection between a server and a client;
  • write about how to receive and send messages.

Further, during the next few weeks I will write another couple of posts on how to set up a flexible architecture to easily handle our game’s networking, and to go into some additional features of Lidgren.Network.

Most important types

  • class NetPeer
    class NetServer : NetPeer
    class NetClient : NetPeer

    In principle Lidgren.Network is a peer to peer library. The base type to handle all network connections is therefore NetPeer. However, the library also natively supports the – for many purposes simpler – client-server architecture, using NetServer and NetClient which inherit from NetPeer.
  • class NetPeerConfiguration
    This type is used to specify the parameters used when setting up any NetPeer. The most important ones will be mentioned below.

  • class NetBuffer
    class NetIncomingMessage : NetBuffer
    class NetOutgoingMessage : NetBuffer

    NetBuffer is essentially a byte array used as base class for both NetIncomingMessage and NetOutgoingMessage, which are used for exactly the purpose that their names suggest. NetBufferoffers a variety of methods to easily read and write all sorts of data to/from the underlying array.

  • enum NetIncomingMessageType
    This enumerator determines the type of an incoming message. These are mostly self-explanatory, and reasonably well documented, but we will also mention the most important values below.

  • enum NetConnectionStatus
    This enumerator represents the status of a connection between two peers (including client and server). These are well documented, but we will again mention the most important ones.

Setting up a server

var config = new NetPeerConfiguration("application name")
{ Port = 12345 };
var server = new NetServer(config);
server.Start();

As you can see in this bit of pseudo code, starting a server could hardly be easier. Important to note is that the application name has to be the same for all connected peers. Lidgren uses this as identification to only consider – hopefully – legitimate connection attempts.
You can of course always do your own validation as well.

The port you specify will be used to listen for incoming messages. In general it is easier to set one yourself, but you can also not do so and let Lidgren find an unused port for you.

When calling Start on your server (and any other NetPeer), Lidgren will bind the appropriate network socket and create a new background thread that handles the networking.

Setting up a client

var config = new NetPeerConfiguration("application name");
var client = new NetClient(config);
client.Start();
client.Connect(host: "127.0.0.1", port: 12345);

Setting up a client is similarly simple and uses virtually the same code as setting up a server.

Note that we do not specify a port here. In fact, there is almost never a good reason to do so, since clients always connect to servers, and never the other way around.

To connect to the server, we simple call Connect, of course with the appropriate IP address and port.

Standard message loop

Once we set up our client or server, we will have to check for new messages regularly – e.g. once per frame. This can be done as follows.
All mentions of peer below can be either servers or clients.

NetIncomingMessage message;
while ((message = peer.ReadMessage()) != null)
{
switch (message.MessageType)
{
case NetIncomingMessageType.Data:
// handle custom messages
var data = message.Read*();
break; case NetIncomingMessageType.StatusChanged:
// handle connection status messages
switch(message.SenderConnection.Status)
{
/* .. */
}
break; case NetIncomingMessageType.DebugMessage:
// handle debug messages
// (only received when compiled in DEBUG mode)
Console.WriteLine(message.ReadString());
break; /* .. */
default:
Console.WriteLine("unhandled message with type: "
+ message.MessageType);
break;
}
}

The MessageType of the received messages indicates what sort of message we received. Most importantly, NetIncomingMessageType.Data is assigned to all messages we send ourselves, and NetIncomingMessageType.StatusChanged messages tell us about new connections, and connections that change status (for example when disconnecting).

Server specific status messages

If as a server we receive a NetIncomingMessageType.StatusChanged message, we should check the NetConnectionStatus of the respective connection, which we can get using message.SenderConnection.Status.

If the status of the connection is Connected, the connection is new, and we should do whatever is necessary to integrate it into the application. We may for example add the new connection to a list of players, and send the new player a list of all already connected players.

If the status is Disconnected, the client disconnected and we should handle that appropriately as well.

There are a couple of other NetConnectionStatus values, but these two are the most important for a simple application.

Client specific status messages

As a client, we will want to check for the same two NetConnectionStatus messages as just mentioned. A value of Connected means that we successfully connected to our server, while Disconnected indicates that connection failed, or that we were disconnected, depending on our previous state.

Sending messages

Now that we can set up and establish a connection we should look at how to send messages to our peers.

Whether we are the client or the server, we first have to create and write to a message as follows:

var message = peer.CreateMessage();
message.Write( /* .. */ );

We can then send that message using one of the following methods:

client.SendMessage(message,
NetDeliveryMethod.ReliableOrdered); server.SendMessage(message, recipient: clientConnection,
NetDeliveryMethod.ReliableOrdered); server.SendMessage(message, recipients: clientConnections,
NetDeliveryMethod.ReliableOrdered, 0);

Note that a message can only be sent a single time. If you want to send a message to multiple clients, you can however use the last overload of SendMessage above and specify a list of connections.

The second parameter of all SendMessage overloads determines how Lidgren will handle package loss and out-of-order messages. Lidgren uses UPD under the hood but has the functionality to both enforce the arrival of all messages, as well as the their order.

For all the available methods, check the documentation on NetDeliveryMethod.

The third parameter of all SendMessage overloads (optional for some) specifies a channel to use when an order-preserving delivery method is used.

Conclusion

This is all you will need to know for setting up a simple networking game or application in C# using Lidgren.Network. As you can see, the basics are fairly simple and I have not had a lot of troubles getting Lidgren to run and do what I want.

Getting a sizeable multiplayer game up and running is of course a bit more complicated. I’ll be sure to post a write-up on the architecture I use in my prototype Syzygy to handle networking as flexibly and easily as I can in a few weeks.

If you are interested, please check out the library’s repository, and my work-in-progress game Syzygy, which uses Lidgren.Network.

Also make sure to check back next Monday, when I will explore a couple of other features of the library which might come in handy.

Enjoy the pixels!

Lidgren.Network – an introduction to networking in C# games的更多相关文章

  1. Lidgren Network Library

    Lidgren Network Library Classes   Class Description NetAESEncryption AES encryption NetBitVector Fix ...

  2. Network Monitoring in Software-Defined Networking :A Review(综述)

    来源:IEEE SYSTEMS JOURNAL 发表时间:2018 类型:综述 主要内容:概述了SDN监控的发展,并从收集信息.预处理.传送信息.分析.和描述五个阶段进行解读,并比较了传统网络和SDN ...

  3. OpenStack Network --- introduction部分 阅读笔记

    Basic Networking 1.混杂模式(promiscuous mode):当网卡被配置为混杂模式时,它们会将所有的frame传递给操作系统,即使MAC地址不匹配. 2.交换机(switch) ...

  4. 【Network】Calico, Flannel, Weave and Docker Overlay Network 各种网络模型之间的区别

    From the previous posts, I have analysed 4 different Docker multi-host network solutions - Calico, F ...

  5. Software-Defined Networking A Comprehensive Survey --阅读_day2

    3. 什么是SDN?(WHAT IS SOFTWARE-DEFINED NETWORKING?) The term SDN was originally coined to represent the ...

  6. Network Experiment Environment Construction

    In order to provide an environment for network experiments in the future, I use VirutalBox to create ...

  7. OpenStack Networking overview

    原文地址:http://docs.openstack.org/newton/install-guide-ubuntu/neutron-concepts.html Networking service ...

  8. 微软职位内部推荐-Sr. SW Engineer for Azure Networking

    微软近期Open的职位: Senior SW Engineer The world is moving to cloud computing. Microsoft is betting Windows ...

  9. Monitoring and Tuning the Linux Networking Stack: Receiving Data

    http://blog.packagecloud.io/eng/2016/06/22/monitoring-tuning-linux-networking-stack-receiving-data/ ...

随机推荐

  1. bzoj 1407 扩展欧几里德

    思路:枚举洞穴个数,用扩展欧几里德暴力判断没两个人的周期. #include<bits/stdc++.h> #define LL long long #define fi first #d ...

  2. HDU 5114 扩展欧几里得

    题目大意:给你两个球的坐标 他们都往(1, 1)这个方向以相同的速度走,问你他们在哪个位置碰撞. 思路:这种题目需要把x方向和y方向分开来算周期,两个不同周期需要用扩展欧几里得来求第一次相遇. #in ...

  3. BZOJ2120/洛谷P1903 [国家集训队] 数颜色 [带修改莫队]

    BZOJ传送门:洛谷传送门 数颜色 题目描述 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R ...

  4. NOI2015 D1T2 软件包管理器

    题目传送门; 这个貌似是我这个蒟蒻做的第一道NOI系列的题了吧...这题的算法是树链剖分,其实基本上就是很常见的树剖+线段树,题目既然是要求每次安装或卸载改变的软件包的数目,那么就在每次操作前记录下线 ...

  5. 单例(LintCode)

    单例 单例 是最为最常见的设计模式之一.对于任何时刻,如果某个类只存在且最多存在一个具体的实例,那么我们称这种设计模式为单例.例如,对于 class Mouse (不是动物的mouse哦),我们应将其 ...

  6. Luogu P3391 【模板】文艺平衡树(FHQ-Treap)

    题意 给出一个长为$n$序列$[1,2,...,n]$,$m$次操作,每次指定一段区间$[l,r]$,将这段区间翻转,求最终序列 题解 虽然标题是$Splay$,但是我要用$FHQ\ Treap$,考 ...

  7. uva 10648(简单dp)

    Recently one of my friend Tarik became a member of the food committee of an ACM regional competition ...

  8. [BZOJ3456]城市规划(生成函数+多项式求逆+多项式求ln)

    城市规划 时间限制:40s      空间限制:256MB 题目描述 刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了.  刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一 ...

  9. [USACO13NOV]No Change

    题目大意: 你有k(k<=16)个硬币,每个硬币都有自己的面值. 现在你要给n件商品付钱,每件商品也有自己的价格. 然而老板是个奸商,他绝对不会给你找钱. 你每次付钱只能用一个硬币,但是你可以一 ...

  10. Problem C: 矩阵对角线求和

    #include<stdio.h> int main() { ][]; scanf("%d",&n); ,sum2=; ;i<n;i++) ;j<n ...