/// <summary> /// Send a message to a specific connection /// </summary> /// <param name="msg">The message to send</param> /// <param name="recipient">The recipient connection</param> /// <param name="method">How to deliver the message</param> /// <param name="sequenceChannel">Sequence channel within the delivery method</param> public NetSendResult SendMessage(NetOutgoingMessage msg, NetConnection recipient, NetDeliveryMethod method, int sequenceChannel) { if (msg == null) { throw new ArgumentNullException("msg"); } if (recipient == null) { throw new ArgumentNullException("recipient"); } if (sequenceChannel >= NetConstants.NetChannelsPerDeliveryMethod) { throw new ArgumentOutOfRangeException("sequenceChannel"); } NetException.Assert( ((method != NetDeliveryMethod.Unreliable && method != NetDeliveryMethod.ReliableUnordered) || ((method == NetDeliveryMethod.Unreliable || method == NetDeliveryMethod.ReliableUnordered) && sequenceChannel == 0)), "Delivery method " + method + " cannot use sequence channels other than 0!" ); NetException.Assert(method != NetDeliveryMethod.Unknown, "Bad delivery method!"); if (msg.m_isSent) { throw new NetException("This message has already been sent! Use NetPeer.SendMessage() to send to multiple recipients efficiently"); } msg.m_isSent = true; bool suppressFragmentation = (method == NetDeliveryMethod.Unreliable || method == NetDeliveryMethod.UnreliableSequenced) && m_configuration.UnreliableSizeBehaviour != NetUnreliableSizeBehaviour.NormalFragmentation; int len = NetConstants.UnfragmentedMessageHeaderSize + msg.LengthBytes; // headers + length, faster than calling msg.GetEncodedSize if (len <= recipient.m_currentMTU || suppressFragmentation) { Interlocked.Increment(ref msg.m_recyclingCount); return(recipient.EnqueueMessage(msg, method, sequenceChannel)); } else { // message must be fragmented! if (recipient.m_status != NetConnectionStatus.Connected) { return(NetSendResult.FailedNotConnected); } // return SendFragmentedMessage(msg, new NetConnection[] { recipient }, method, sequenceChannel); var tmp = ConnectionListPool.Rent(); tmp.Add(recipient); var result = SendFragmentedMessage(msg, tmp, method, sequenceChannel); ConnectionListPool.Return(tmp); return(result); } }
/// <summary> /// Gets a copy of the list of connections /// </summary> public List <NetConnection> GetConnections() { var list = ConnectionListPool.Rent(); lock (m_connections) { foreach (var conn in m_connections) { list.Add(conn); } } return(list); }
/// <summary> /// Send a message to all connections except one /// </summary> /// <param name="msg">The message to send</param> /// <param name="method">How to deliver the message</param> /// <param name="except">Don't send to this particular connection</param> /// <param name="sequenceChannel">Which sequence channel to use for the message</param> public void SendToAll(NetOutgoingMessage msg, NetConnection except, NetDeliveryMethod method, int sequenceChannel) { // Modifying m_connections will modify the list of the connections of the NetPeer. Do only reads here var all = m_connections; if (all.Count <= 0) { if (msg.m_isSent == false) { Recycle(msg); } return; } if (except == null) { SendMessage(msg, all, method, sequenceChannel); return; } var recipients = ConnectionListPool.Rent(); foreach (var conn in all) { if (conn != except) { recipients.Add(conn); } } if (recipients.Count > 0) { SendMessage(msg, recipients, method, sequenceChannel); } ConnectionListPool.Return(recipients); }
private void ExecutePeerShutdown() { VerifyNetworkThread(); LogDebug("Shutting down..."); // disconnect and make one final heartbeat var list = ConnectionListPool.Rent(); lock (m_connections) { foreach (var conn in m_connections) { if (conn != null) { list.Add(conn); } } } lock (m_handshakes) { foreach (var hs in m_handshakes.Values) { if (hs != null && list.Contains(hs) == false) { list.Add(hs); } } } // shut down connections foreach (NetConnection conn in list) { conn.Shutdown(m_shutdownReason); } ConnectionListPool.Return(list); FlushDelayedPackets(); // one final heartbeat, will send stuff and do disconnect Heartbeat(); NetUtility.Sleep(10); lock (m_initializeLock) { try { if (m_socket != null) { try { m_socket.Shutdown(SocketShutdown.Receive); } catch (Exception ex) { LogDebug("Socket.Shutdown exception: " + ex.ToString()); } try { m_socket.Close(2); // 2 seconds timeout } catch (Exception ex) { LogDebug("Socket.Close exception: " + ex.ToString()); } } } finally { m_socket = null; m_status = NetPeerStatus.NotRunning; LogDebug("Shutdown complete"); // wake up any threads waiting for server shutdown if (m_messageReceivedEvent != null) { m_messageReceivedEvent.Set(); } } m_lastSocketBind = float.MinValue; m_receiveBuffer = null; m_sendBuffer = null; m_unsentUnconnectedMessages.Clear(); m_connections.Clear(); m_connectionLookup.Clear(); m_handshakes.Clear(); } return; }