我是靠谱客的博主 如意手机,这篇文章主要介绍Peer to Peer Networking Example Using the Lidgren.Network Framework,现在分享给大家,希望可以做个参考。

http://www.tylerforsythe.com/2011/11/peer-to-peer-networking-example-using-the-lidgren-network-framework/

Brief topic switch: Peer to peer networking. I had wanted to get this example in a simple movement game in IceCream but found I needed to start with a console app first. So here it is. I’ve cleverly named it NetConsoles, and the purpose is to teach myself how to link multiple nodes in a peer to peer fashion using the Lidgren.Network framework. While I had some initial issues, it wasn’t all that hard.

Nearly every example I could find using Lidgren.Network was a client/server architecture, so I had to do quite a bit of experimenting to get peer to peer going. Finding sample code for it was completely fruitless. But I did see a post indicating it is possible and relatively easy, so I pressed on. It turns out that the base object of NetClient and NetServer is NetPeer, and it’s all you need to connect p2p (I’m now tired of typing it out).

Two things stand out from this experience: the first is that I tried to create a semi-contained and reusable networking object. It’s far from robust, but I think it will be a sufficient base to carry into my next networking endeavor. The second is that I don’t typically need to do much threading, but it was necessary for this application. The reason is that we need to be constantly polling for incoming network data while also waiting for the user to type commands (like to send a test message). Console.WriteLine is blocking, so my main networking object is written so that when Listen() is called, it spins off a thread that continuously asks Lidgren.Network, “do we have messages to process?” If yes, parse and handle. While basic, I enjoyed the exercise because threads are not in my day to day toolbox (but maybe they should be!).

You can download all the code here, which includes binaries, in case people have trouble building: NetConsoles

Note that the folder structure expects the lidgren-network-gen3 folder to be just one-level above the solution folder. I’d rather include the code library than just a DLL to make debugging and stepping through easier. While learning, it was very handle to be able to visually scan the internal workings of the library rather than be stuck with just IntelliSense (even though IntelliSense is very nice).

Some highlights of the code include:

Construction of the NetPeerConfiguration object (only the first two NetIncomingMessageType are required for basic functionality, but I wanted to see the other 2 in action).

复制代码
1
2
3
4
5
6
Config = new NetPeerConfiguration("test_console"); Config.EnableMessageType(NetIncomingMessageType.DiscoveryRequest); Config.EnableMessageType(NetIncomingMessageType.DiscoveryResponse); Config.EnableMessageType(NetIncomingMessageType.ConnectionApproval); Config.EnableMessageType(NetIncomingMessageType.UnconnectedData); Config.LocalAddress = NetUtility.Resolve("localhost");

The initialization of the NetPeer object (extremely simple) and starting up the listener thread:

复制代码
1
2
3
4
5
6
7
Peer = new NetPeer(Config); Peer.Start(); Console.WriteLine("listening on " + Config.Port.ToString());   NetWorker = new MyNetWorker(Peer, this); NetThread = new Thread(NetWorker.ProcessNet); NetThread.Start();

Sending a basic string message (the MessageType enum is my own, not part of the framework):

复制代码
1
2
3
4
5
6
7
8
9
10
public void SendMessage(string message) { if (Peer.Connections == null || Peer.Connections.Count == 0) { Console.WriteLine("No connections to send to."); return; } NetOutgoingMessage msg = Peer.CreateMessage(); msg.Write((int)MessageType.StringMessage); msg.Write(message); Peer.SendMessage(msg, Peer.Connections, NetDeliveryMethod.ReliableOrdered, 0); }

Sending peer info to all connected peers (by passing Peer.Connections to Peer.SendMessage):

复制代码
1
2
3
4
5
6
7
8
9
10
11
public void SendPeerInfo(IPAddress ip, int port) { Console.WriteLine(string.Format("Broadcasting {0}:{1} to all (count: {2})", ip.ToString(), port.ToString(), Peer.ConnectionsCount)); NetOutgoingMessage msg = Peer.CreateMessage(); msg.Write((int)MessageType.PeerInformation); byte[] addressBytes = ip.GetAddressBytes(); msg.Write(addressBytes.Length); msg.Write(addressBytes); msg.Write(port); Peer.SendMessage(msg, Peer.Connections, NetDeliveryMethod.ReliableOrdered, 0); }

And finally–huge code dump–the listen thread class:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
public class MyNetWorker { NetPeer peer = null; NetManager netManager = null; public volatile bool shouldQuit = false;   public MyNetWorker(NetPeer inPeer, NetManager inNetManager) { peer = inPeer; netManager = inNetManager; }   public void ProcessNet() { // read messages while (!shouldQuit) { Thread.Sleep(1); if (peer == null) continue; NetIncomingMessage msg; while ((msg = peer.ReadMessage()) != null) { switch (msg.MessageType) { case NetIncomingMessageType.DiscoveryRequest: Console.WriteLine("ReceivePeersData DiscoveryRequest"); peer.SendDiscoveryResponse(null, msg.SenderEndpoint); break; case NetIncomingMessageType.DiscoveryResponse: // just connect to first server discovered Console.WriteLine("ReceivePeersData DiscoveryResponse CONNECT"); peer.Connect(msg.SenderEndpoint); break; case NetIncomingMessageType.ConnectionApproval: Console.WriteLine("ReceivePeersData ConnectionApproval"); msg.SenderConnection.Approve(); //broadcast this to all connected clients //msg.SenderEndpoint.Address, msg.SenderEndpoint.Port netManager.SendPeerInfo(msg.SenderEndpoint.Address, msg.SenderEndpoint.Port); break; case NetIncomingMessageType.Data: //another client sent us data Console.WriteLine("BEGIN ReceivePeersData Data"); MessageType mType = (MessageType)msg.ReadInt32(); if (mType == MessageType.StringMessage) { Console.WriteLine("Message received: " + msg.ReadString()); } else if (mType == MessageType.PeerInformation) { Console.WriteLine("Data::PeerInfo BEGIN"); int byteLenth = msg.ReadInt32(); byte[] addressBytes = msg.ReadBytes(byteLenth); IPAddress ip = new IPAddress(addressBytes); int port = msg.ReadInt32(); //connect IPEndPoint endPoint = new IPEndPoint(ip, port); Console.WriteLine("Data::PeerInfo::Detecting if we're connected"); if (peer.GetConnection(endPoint) == null) {//are we already connected? //Don't try to connect to ourself! if (peer.Configuration.LocalAddress.GetHashCode() != endPoint.Address.GetHashCode() || peer.Configuration.Port.GetHashCode() != endPoint.Port.GetHashCode()) { Console.WriteLine(string.Format("Data::PeerInfo::Initiate new connection to: {0}:{1}", endPoint.Address.ToString(), endPoint.Port.ToString())); peer.Connect(endPoint); } } Console.WriteLine("Data::PeerInfo END"); } Console.WriteLine("END ReceivePeersData Data"); break; case NetIncomingMessageType.UnconnectedData: string orphanData = msg.ReadString(); Console.WriteLine("UnconnectedData: " + orphanData); break; default: Console.WriteLine("ReceivePeersData Unknown type: " + msg.MessageType.ToString()); try { Console.WriteLine(msg.ReadString()); } catch { Console.WriteLine("Couldn't parse unknown to string."); } break; } } } Console.WriteLine("Exiting net thread!"); } }

Whew! It’s a lot, but p2p is pretty cool! Good luck!

最后

以上就是如意手机最近收集整理的关于Peer to Peer Networking Example Using the Lidgren.Network Framework的全部内容,更多相关Peer内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部