private void ListenClients() { _serverSocket.Start(); while (_runningServer) { try { while (!_serverSocket.Pending()) { Thread.Sleep(100); } TcpClient clientSocket = _serverSocket.AcceptTcpClient(); ClientCommunicator client = new ClientCommunicator(clientSocket); client.OnPacketReceive += ParsePacket; client.OnDeadCommunicator += (receiver, exception) => { OnLogMessage(receiver, "[" + Thread.CurrentThread.ManagedThreadId+ "] Remove dead/disconnected communicator " + receiver.ClientRemoteId); if (exception!=null) OnLogMessage(receiver, "Message from client receiver: " +exception.Message); receiver.Stop(); _clients.Remove(receiver); //if (exception is IOException || exception is SocketException) //{ // OnLogMessage(receiver, "Remove dead/disconnected communicator " + receiver.ClientSocket.Client.RemoteEndPoint.ToString()); //} //else // throw exception; }; _clients.Add(client); client.Start(); OnLogMessage(client,"accepted"); } catch (Exception ex) { if (ex is IOException || ex is SocketException) { if (!ex.Message.Contains("WSACancelBlockingCall")) throw; } else if (ex is ThreadAbortException || ex is ThreadInterruptedException) return; else throw; } } }
public void ParsePacket(ClientCommunicator client, Packet packet) { if (packet.Opcode == Opcodes.Invalid) return; OnLogMessage(client, "[" + Thread.CurrentThread.ManagedThreadId + "] Received opcode:" + Enum.GetName(typeof(Opcodes), packet.Opcode)); switch (packet.Opcode) { case Opcodes.NotifyAll: { NotifyData inputNotifyData = new NotifyData(packet.Data); NotifyData outputNotifyData = new NotifyData(Guid.Empty, inputNotifyData.Data, false); Packet outputpacket = new Packet(Guid.NewGuid(), Opcodes.NotifyAll, outputNotifyData.Pack()); foreach (ClientCommunicator communicator in _clients) { if (client.Equals(communicator)) { if (inputNotifyData.NotifySelf) communicator.SendData(outputpacket); } else { communicator.SendData(outputpacket); } } break; } case Opcodes.NotifyApp: { NotifyData inputNotifyData = new NotifyData(packet.Data); var subs = GetAppSubscribers(inputNotifyData.AppId); IEnumerable<ClientCommunicator> clientCommunicators = subs as IList<ClientCommunicator> ?? subs.ToList(); if (clientCommunicators.Any()) { NotifyData outputNotifyData = new NotifyData(inputNotifyData.AppId, inputNotifyData.Data, false); Packet outputpacket = new Packet(Guid.NewGuid(), Opcodes.NotifyApp, outputNotifyData.Pack()); foreach (ClientCommunicator communicator in clientCommunicators) { if (client.Equals(communicator)) { if (inputNotifyData.NotifySelf) communicator.SendData(outputpacket); } else { communicator.SendData(outputpacket); } } } break; } case Opcodes.Subscribe: { Guid appId; if (Guid.TryParse(packet.Data, out appId)) { var subs = GetAppSubscribers(appId); var sub = subs.SingleOrDefault(s => s.Equals(client)); if (sub == null) { client.ApplicationId = appId; OnLogMessage(client, "[" + Thread.CurrentThread.ManagedThreadId + "] subscribe to " + appId); } else { OnLogMessage(client, "[" + Thread.CurrentThread.ManagedThreadId + "] already subscribed"); } } break; } case Opcodes.Unsubscribe: { Guid appId; if (Guid.TryParse(packet.Data, out appId)) { var subs = GetAppSubscribers(appId); var sub = subs.SingleOrDefault(s => s.Equals(client)); if (sub != null) { sub.ApplicationId = Guid.Empty; OnLogMessage(client, "[" + Thread.CurrentThread.ManagedThreadId + "] unsubscribe from " + appId); } else { OnLogMessage(client, "[" + Thread.CurrentThread.ManagedThreadId + "] not subscribed"); } } break; } default: OnLogMessage(client, "[" + Thread.CurrentThread.ManagedThreadId + "] Unknown opcode " + packet.Opcode.ToString()); break; } }