프로젝트

일반

사용자정보

통계
| 브랜치(Branch): | 개정판:

markus / Rhino.Licensing / Discovery / DiscoveryHost.cs @ 42d49521

이력 | 보기 | 이력해설 | 다운로드 (4.42 KB)

1
using System;
2
using System.IO;
3
using System.Net;
4
using System.Net.NetworkInformation;
5
using System.Net.Sockets;
6
using System.Linq;
7
//using log4net;
8

    
9
namespace Rhino.Licensing.Discovery
10
{
11
	///<summary>
12
	/// Listen to precense notifications
13
	///</summary>
14
	public class DiscoveryHost : IDisposable
15
	{
16
		private Socket socket;
17
		private readonly byte[] buffer = new byte[1024*4];
18
		private const string AllHostsMulticastIP = "224.0.0.1";
19
		private const int DiscoveryPort = 12391;
20
        //private static readonly ILog Log = LogManager.GetLogger(typeof(DiscoveryHost));
21

    
22
		///<summary>
23
		/// Starts listening to network notifications
24
		///</summary>
25
		public void Start()
26
		{
27
			socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
28
			socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
29
			BindUpAdaptersToMulticast();
30
			socket.Bind(new IPEndPoint(IPAddress.Any, DiscoveryPort));
31
			StartListening();
32
		}
33

    
34
		private void BindUpAdaptersToMulticast()
35
		{
36
			NetworkInterface.GetAllNetworkInterfaces()
37
				.Where(card => card.OperationalStatus == OperationalStatus.Up)
38
				.ToList()
39
				.ForEach(SetSocketOptionsForNic);
40
		}
41

    
42
		private void SetSocketOptionsForNic(NetworkInterface nic)
43
		{
44
		    nic.GetIPProperties()
45
		        .UnicastAddresses
46
		        .Where(unicast => unicast.Address.AddressFamily == AddressFamily.InterNetwork)
47
		        .ToList()
48
		        .ForEach(SafelySetSocketOptionsForAddress);
49
		}
50

    
51
	    private void SafelySetSocketOptionsForAddress(UnicastIPAddressInformation address)
52
	    {
53
	        try
54
	        {
55
	            socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership,
56
	                new MulticastOption(IPAddress.Parse(AllHostsMulticastIP), address.Address));
57
	        }
58
	        catch (SocketException ex)
59
	        {
60
                throw new Exception($"Setting socket options failed for address: {address?.Address}", ex);
61
                //Log.Warn($"Setting socket options failed for address: {address?.Address}", ex);
62
	        }
63
	    }
64

    
65
		private void StartListening()
66
		{
67
			var socketAsyncEventArgs = new SocketAsyncEventArgs
68
			{
69
				RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0),
70
			};
71
			socketAsyncEventArgs.Completed += Completed;
72
			socketAsyncEventArgs.SetBuffer(buffer, 0, buffer.Length);
73

    
74
			bool startedAsync;
75
			try
76
			{
77
				startedAsync = socket.ReceiveFromAsync(socketAsyncEventArgs);
78
			}
79
			catch (Exception)
80
			{
81
				return;
82
			}
83
			if (startedAsync == false)
84
				Completed(this, socketAsyncEventArgs);
85
		}
86

    
87
		private void Completed(object sender, SocketAsyncEventArgs socketAsyncEventArgs)
88
		{
89
			using (socketAsyncEventArgs)
90
			{
91
				try
92
				{
93
					using (var stream = new MemoryStream(socketAsyncEventArgs.Buffer, 0, socketAsyncEventArgs.BytesTransferred))
94
					using (var streamReader = new StreamReader(stream))
95
					{
96
						var senderId = streamReader.ReadLine();
97
						var userId = streamReader.ReadLine();
98
						var clientDiscovered = new ClientDiscoveredEventArgs
99
						{
100
							MachineName = streamReader.ReadLine(),
101
							UserName = streamReader.ReadLine()
102
						};
103

    
104
						Guid result;
105
						if (Guid.TryParse(userId, out result))
106
						{
107
							clientDiscovered.UserId = result;
108
						}
109

    
110
						if (Guid.TryParse(senderId, out result))
111
						{
112
							clientDiscovered.SenderId = result;
113
							InvokeClientDiscovered(clientDiscovered);
114
						}
115
					}
116
				}
117
				catch
118
				{
119
				}
120
				StartListening();
121
			}
122
		}
123

    
124
		///<summary>
125
		/// Notify when a client is discovered
126
		///</summary>
127
		public event EventHandler<ClientDiscoveredEventArgs> ClientDiscovered;
128

    
129
		private void InvokeClientDiscovered(ClientDiscoveredEventArgs e)
130
		{
131
			EventHandler<ClientDiscoveredEventArgs> handler = ClientDiscovered;
132
			if (handler != null) handler(this, e);
133
		}
134

    
135
		/// <summary>
136
		/// Notification raised when a client is discovered
137
		/// </summary>
138
		public class ClientDiscoveredEventArgs : EventArgs
139
		{
140
			/// <summary>
141
			/// The client's license id
142
			/// </summary>
143
			public Guid UserId { get; set; }
144

    
145
			/// <summary>
146
			/// The client machine name
147
			/// </summary>
148
			public string MachineName { get; set; }
149

    
150
			/// <summary>
151
			/// The client user name
152
			/// </summary>
153
			public string UserName { get; set; }
154

    
155
			/// <summary>
156
			/// The id of the sender
157
			/// </summary>
158
			public Guid SenderId { get; set; }
159

    
160
		}
161

    
162
        /// <summary>
163
        /// Disposes of the object
164
        /// </summary>
165
		public void Dispose()
166
		{
167
			if (socket != null)
168
				socket.Dispose();
169
		}
170
	}
171
}
클립보드 이미지 추가 (최대 크기: 500 MB)