Пример #1
0
 // unsequenced packets only, returns number of bytes sent
 internal int SendSingleMessageAtOnce(NetMessage msg, NetConnection connection, IPEndPoint endpoint)
 {
     m_sendBuffer.ResetWritePointer();
     msg.Encode(connection, m_sendBuffer);
     if (connection != null)
     {
         return(ExecuteSend(m_sendBuffer, connection, connection.RemoteEndpoint));
     }
     else
     {
         return(ExecuteSend(m_sendBuffer, null, endpoint));
     }
 }
Пример #2
0
        public void DiscoverLocalServers(int serverPort)
        {
            IPEndPoint broadcast = new IPEndPoint(IPAddress.Broadcast, serverPort);
            NetMessage msg       = NetDiscovery.EncodeRequest(this);

            Log.Info("Broadcasting server discovery ping...");

            // special send style; can't use simulated lag due to socket options
            try
            {
                m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);

                m_sendBuffer.ResetWritePointer();
                msg.Encode(null, m_sendBuffer);

                int bytesSent = m_socket.SendTo(m_sendBuffer.Data, 0, m_sendBuffer.LengthBytes, SocketFlags.None, broadcast);
                Log.Verbose(string.Format(CultureInfo.InvariantCulture, "Sent {0} bytes to {1}", bytesSent, broadcast));
                return;
            }
            catch (SocketException sex)
            {
                if (sex.SocketErrorCode == SocketError.ConnectionReset ||
                    sex.SocketErrorCode == SocketError.ConnectionRefused ||
                    sex.SocketErrorCode == SocketError.ConnectionAborted)
                {
                    Log.Warning("Remote socket forcefully closed: " + sex.SocketErrorCode);
                    return;
                }

                Log.Warning("Execute SocketException: " + sex.SocketErrorCode);
                return;
            }
            finally
            {
                m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, false);
            }
        }
Пример #3
0
        internal void SendUnsentMessages(bool forceAcks, double frameLength)
        {
            if (m_unsentMessages.Count < 1 && !forceAcks)
            {
                if (m_status == NetConnectionStatus.Disconnecting)
                {
                    SetStatus(NetConnectionStatus.Disconnected, m_pendingDisconnectedReason);
                }
                return;                 // nothing to send
            }

            //if (m_unsentMessages.Count < 1 && forceAcks)
            //	m_parent.Log.Debug("FORCING EXPLICIT ACK");

            float sendBytesAllowed = (float)frameLength * (float)Configuration.ThrottleBytesPerSecond;

            if (m_throttleDebt > sendBytesAllowed)
            {
                // NetBase.CurrentContext.Log.Debug("Working off debt: " + m_throttleDebt + " bytes by " + sendBytesAllowed");
                m_throttleDebt -= sendBytesAllowed;
                return;
            }
            else if (m_throttleDebt > 0)
            {
                sendBytesAllowed -= m_throttleDebt;
                m_throttleDebt    = 0;
            }

            NetBuffer sendBuffer = m_parent.m_sendBuffer;

            sendBuffer.ResetWritePointer();

            int mtu = m_parent.Configuration.MaximumTransmissionUnit;

            float now = (float)NetTime.Now;

            int        pktMsgAdded = 0;
            int        ackMsgAdded = 0;
            int        usrMsgAdded = 0;
            NetMessage msg;

            // TODO: make ack bitfield if possible

            while (m_unsentAcknowledges.Count > 0 && sendBytesAllowed > 0)
            {
                msg = m_unsentAcknowledges.Dequeue();
                m_reusedAckMessage.SequenceChannel = msg.SequenceChannel;
                m_reusedAckMessage.SequenceNumber  = msg.SequenceNumber;

                if (sendBuffer.LengthBytes + 3 > mtu)
                {
                    // send buffer
                    m_parent.ExecuteSend(sendBuffer, this, m_remoteEndpoint);
                    sendBytesAllowed -= sendBuffer.LengthBytes;

                    Statistics.PacketsSent++;
                    Statistics.MessagesSent    += pktMsgAdded;
                    Statistics.AckMessagesSent += ackMsgAdded;
                    Statistics.BytesSent       += sendBuffer.LengthBytes;

                    sendBuffer.ResetWritePointer();
                    pktMsgAdded = 0;
                    ackMsgAdded = 0;
                }

                //m_parent.Log.Debug("Sending ack " + msg.SequenceChannel + "|" + msg.SequenceNumber);
                m_reusedAckMessage.Encode(this, sendBuffer);
                pktMsgAdded++;
                ackMsgAdded++;
            }

            // no unsent acks left!
            m_forceExplicitAckTime = 0.0;

            while (m_unsentMessages.Count > 0 && sendBytesAllowed > 0)
            {
                msg = m_unsentMessages.Dequeue();

                // make pessimistic estimate of message length
                int estMsgLen = msg.EstimateEncodedLength();

                if (sendBuffer.LengthBytes + estMsgLen > mtu)
                {
                    if (pktMsgAdded < 1)
                    {
                        throw new NetException("Message too large to send: " + estMsgLen + " bytes: " + msg);
                    }

                    // send buffer
                    m_parent.ExecuteSend(sendBuffer, this, m_remoteEndpoint);
                    sendBytesAllowed -= sendBuffer.LengthBytes;

                    Statistics.PacketsSent++;
                    Statistics.MessagesSent     += pktMsgAdded;
                    Statistics.UserMessagesSent += usrMsgAdded;
                    Statistics.AckMessagesSent  += ackMsgAdded;
                    Statistics.BytesSent        += sendBuffer.LengthBytes;

                    sendBuffer.ResetWritePointer();
                    pktMsgAdded = 0;
                    ackMsgAdded = 0;
                }

                msg.Encode(this, sendBuffer);
                if (msg.m_type == NetMessageType.User || msg.m_type == NetMessageType.UserFragmented)
                {
                    usrMsgAdded++;
                }
                pktMsgAdded++;

                // store until acknowledged
                if (msg.SequenceChannel >= NetChannel.ReliableUnordered)
                {
                    float nextResend = now + (msg.m_numResends < 1 ? Configuration.ResendFirstUnacknowledgedDelay : Configuration.ResendSubsequentUnacknowledgedDelay);
                    msg.m_nextResendTime = nextResend;
                    //m_parent.Log.Debug("Storing " + msg.SequenceChannel + "|" + msg.SequenceNumber + " @ " + now + " first resend: " + nextResend);
                    int seqChan = (int)msg.SequenceChannel;
                    if (m_savedReliableMessages[seqChan] == null)
                    {
                        m_savedReliableMessages[seqChan] = new List <NetMessage>();
                    }
                    m_savedReliableMessages[seqChan].Add(msg);
                }
            }

            if (pktMsgAdded > 0)
            {
                m_parent.ExecuteSend(sendBuffer, this, m_remoteEndpoint);
                sendBytesAllowed -= sendBuffer.LengthBytes;
                Statistics.PacketsSent++;
                Statistics.MessagesSent     += pktMsgAdded;
                Statistics.UserMessagesSent += usrMsgAdded;
                Statistics.AckMessagesSent  += ackMsgAdded;
                Statistics.BytesSent        += sendBuffer.LengthBytes;
            }

            Debug.Assert(m_throttleDebt == 0);
            if (sendBytesAllowed < 0)
            {
                m_throttleDebt = -sendBytesAllowed;
            }
        }
Пример #4
0
 // unsequenced packets only, returns number of bytes sent
 internal int SendSingleMessageAtOnce(NetMessage msg, NetConnection connection, IPEndPoint endpoint)
 {
     m_sendBuffer.ResetWritePointer();
     msg.Encode(connection, m_sendBuffer);
     if (connection != null)
         return ExecuteSend(m_sendBuffer, connection, connection.RemoteEndpoint);
     else
         return ExecuteSend(m_sendBuffer, null, endpoint);
 }