Пример #1
0
        private bool SendOutMessage(NetOutgoingMessage msg, IPEndPoint endPoint)
        {
            byte[] data = new byte[msg.GetEncodedSize()];
            int    len  = msg.Encode(data, 0, 0);

            try
            {
                peer.Send(data, data.Length, endPoint);
            }
            catch (Exception e)
            {
                Debug.LogError("Cannot send message to MS. \n" + e.ToString());
                // if udp client has a connection socket, than forget it
                return(false);
            }

            return(true);
        }
            /// <summary>
            /// Send a message to a list of connections
            /// </summary>
            /// <param name="msg">The message to send</param>
            /// <param name="recipients">The list of recipients to send to</param>
            /// <param name="method">How to deliver the message</param>
            /// <param name="sequenceChannel">Sequence channel within the delivery method</param>
            public void SendMessage(NetOutgoingMessage msg, List<NetConnection> recipients, NetDeliveryMethod method, int sequenceChannel)
            {
                if (msg == null)
                    throw new ArgumentNullException("msg");
                if (recipients == null)
                    throw new ArgumentNullException("recipients");
                if (recipients.Count < 1)
                    throw new NetException("recipients must contain at least one item");
                if (method == NetDeliveryMethod.Unreliable || method == NetDeliveryMethod.ReliableUnordered)
                    NetException.Assert(sequenceChannel == 0, "Delivery method " + method + " cannot use sequence channels other than 0!");
                if (msg.m_isSent)
                    throw new NetException("This message has already been sent! Use NetPeer.SendMessage() to send to multiple recipients efficiently");

                int mtu = GetMTU(recipients);

                msg.m_isSent = true;

                int len = msg.GetEncodedSize();
                if (len <= mtu)
                {
                    Interlocked.Add(ref msg.m_recyclingCount, recipients.Count);
                    foreach (NetConnection conn in recipients)
                    {
                        if (conn == null)
                        {
                            Interlocked.Decrement(ref msg.m_recyclingCount);
                            continue;
                        }
                        NetSendResult res = conn.EnqueueMessage(msg, method, sequenceChannel);
                        if (res != NetSendResult.Queued && res != NetSendResult.Sent)
                            Interlocked.Decrement(ref msg.m_recyclingCount);
                    }
                }
                else
                {
                    // message must be fragmented!
                    SendFragmentedMessage(msg, recipients, method, sequenceChannel);
                }

                return;
            }
            // called by SendMessage() and NetPeer.SendMessage; ie. may be user thread
            internal NetSendResult EnqueueMessage(NetOutgoingMessage msg, NetDeliveryMethod method, int sequenceChannel)
            {
                if (m_status != NetConnectionStatus.Connected)
                    return NetSendResult.FailedNotConnected;

                NetMessageType tp = (NetMessageType)((int)method + sequenceChannel);
                msg.m_messageType = tp;

                // TODO: do we need to make this more thread safe?
                int channelSlot = (int)method - 1 + sequenceChannel;
                NetSenderChannelBase chan = m_sendChannels[channelSlot];
                if (chan == null)
                    chan = CreateSenderChannel(tp);

                if (msg.GetEncodedSize() > m_currentMTU)
                    throw new NetException("Message too large! Fragmentation failure?");

                var retval = chan.Enqueue(msg);
                if (retval == NetSendResult.Sent && m_peerConfiguration.m_autoFlushSendQueue == false)
                    retval = NetSendResult.Queued; // queued since we're not autoflushing
                return retval;
            }
            // Queue an item for immediate sending on the wire
            // This method is called from the ISenderChannels
            internal void QueueSendMessage(NetOutgoingMessage om, int seqNr)
            {
                m_peer.VerifyNetworkThread();

                int sz = om.GetEncodedSize();
                if (sz > m_currentMTU)
                    m_peer.LogWarning("Message larger than MTU! Fragmentation must have failed!");

                if (m_sendBufferWritePtr + sz > m_currentMTU)
                {
                    bool connReset; // TODO: handle connection reset
                    NetException.Assert(m_sendBufferWritePtr > 0 && m_sendBufferNumMessages > 0); // or else the message should have been fragmented earlier
                    m_peer.SendPacket(m_sendBufferWritePtr, m_remoteEndPoint, m_sendBufferNumMessages, out connReset);
                    m_statistics.PacketSent(m_sendBufferWritePtr, m_sendBufferNumMessages);
                    m_sendBufferWritePtr = 0;
                    m_sendBufferNumMessages = 0;
                }

                m_sendBufferWritePtr = om.Encode(m_peer.m_sendBuffer, m_sendBufferWritePtr, seqNr);
                m_sendBufferNumMessages++;

                NetException.Assert(m_sendBufferWritePtr > 0, "Encoded zero size message?");
                NetException.Assert(m_sendBufferNumMessages > 0);
            }