示例#1
0
        public void Close()
        {
            lock (stateLock)
            {
                if (state != State.Started)
                {
                    return;
                }

                state = State.Closing;

                DemonitorTask(receiver);
                receiver.Stop();

                DemonitorTask(receiver);
                sender.Stop();

                socket.Send(BinaryMessage.Make(MSG_CLOSE).Complete());
                // HACK: otherwise close message may not be sent
                Thread.Sleep(TimeSpan.FromMilliseconds(5));
                socket.Close();

                state = State.Closed;
            }
            Dispatcher.Dispatch(new ExitMessage());
        }
示例#2
0
        public void Send(BinaryMessage message)
        {
            var buffer = new byte[message.Length + 1];

            buffer[0] = message.Type;
            Array.Copy(message.GetData(), 0, buffer, 1, message.Length);
            socket.Send(buffer);
        }
示例#3
0
 public PendingMessage(ushort seq, BinaryMessage message)
 {
     Type       = message.Type;
     Content    = message.GetData();
     Seq        = seq;
     Last       = DateTime.Now;
     RetryCount = 0;
 }
示例#4
0
        protected void AckGobData(long gobId, int frame)
        {
            var message = BinaryMessage.Make(MSG_OBJACK)
                          .UInt32((uint)gobId)
                          .Int32(frame)
                          .Complete();

            // FIXME: make it smarter
            socket.Send(message);
        }
示例#5
0
 public void SendSeqMessage(BinaryMessage message)
 {
     lock (pending)
     {
         pending.Add(new PendingMessage(pendingSeq, message));
         pendingSeq++;
     }
     lock (thisLock)
         Monitor.PulseAll(thisLock);
 }
示例#6
0
        public void ReadWriteTest()
        {
            var input = BinaryMessage.Make(1)
                        .String("Test")
                        .UInt16(64)
                        .String("Test2")
                        .Complete();

            var output = new BinaryMessage(1, input.GetData());

            Assert.AreEqual(output.Type, input.Type);

            using (var reader = output.GetReader())
            {
                Assert.AreEqual("Test", reader.ReadCString());
                Assert.AreEqual(64, reader.ReadUInt16());
                Assert.AreEqual("Test2", reader.ReadCString());
            }
        }
示例#7
0
        private void ReceiveMessage(BinaryMessage msg)
        {
            var reader = msg.GetReader();

            switch (msg.Type)
            {
            case MSG_REL:
                var seq = reader.ReadUInt16();
                while (reader.HasRemaining)
                {
                    var type = reader.ReadByte();
                    int len;
                    if ((type & 0x80) != 0)                             // is not last?
                    {
                        type &= 0x7f;
                        len   = reader.ReadUInt16();
                    }
                    else
                    {
                        len = (int)reader.Remaining;
                    }
                    ReceiveSeqMessage(seq, new BinaryMessage(type, reader.ReadBytes(len)));
                    seq++;
                }
                break;

            case MSG_ACK:
                sender.ReceiveAck(reader.ReadUInt16());
                break;

            case MSG_MAPDATA:
                HandleMapData(msg.GetReader());
                break;

            case MSG_OBJDATA:
                HandleGobData(msg.GetReader());
                break;

            case MSG_CLOSE:
                Close();
                return;
            }
        }
示例#8
0
 private void ReceiveSeqMessage(ushort seq, BinaryMessage msg)
 {
     if (seq == rseq)
     {
         HandleSeqMessage(msg);
         while (true)
         {
             rseq++;
             if (!waiting.Remove(rseq, out msg))
             {
                 break;
             }
             HandleSeqMessage(msg);
         }
         sender.SendAck((ushort)(rseq - 1));
     }
     else if (seq > rseq)
     {
         waiting[seq] = msg;
     }
 }
示例#9
0
        public bool Receive(out BinaryMessage message)
        {
            if (!socket.Poll(receiveTimeout * 1000, SelectMode.SelectRead))
            {
                message = null;
                return(false);
            }

            int size = socket.Receive(receiveBuffer);

            if (size == 0)
            {
                throw new Exception("Couldn't receive data from socket");
            }
            var type   = receiveBuffer[0];
            var buffer = new byte[size - 1];

            Array.Copy(receiveBuffer, 1, buffer, 0, size - 1);

            message = new BinaryMessage(type, buffer);
            return(true);
        }
示例#10
0
 protected void SendSeqMessage(BinaryMessage message)
 {
     sender.SendSeqMessage(message);
 }
示例#11
0
 protected void Send(BinaryMessage message)
 {
     socket.Send(message);
 }
示例#12
0
 protected abstract void HandleSeqMessage(BinaryMessage message);
示例#13
0
        protected override void OnStart()
        {
            var last = DateTime.Now;

            while (!IsCancelled)
            {
                var to   = TimeSpan.FromMilliseconds(5000);
                var now  = DateTime.Now;
                var beat = true;

                lock (pending)
                {
                    if (pending.Count > 0)
                    {
                        to = TimeSpan.FromMilliseconds(60);
                    }
                }
                lock (thisLock)
                {
                    if (ackTime.HasValue)
                    {
                        to = ackTime.Value - now + TimeSpan.FromMilliseconds(AckThreshold);
                    }
                    if (to.TotalMilliseconds > 0)
                    {
                        Monitor.Wait(thisLock, to);
                    }
                }

                lock (pending)
                {
                    foreach (var msg in pending)
                    {
                        int txtime;

                        if (msg.RetryCount == 0)
                        {
                            txtime = 0;
                        }
                        else if (msg.RetryCount == 1)
                        {
                            txtime = 80;
                        }
                        else if (msg.RetryCount < 4)
                        {
                            txtime = 200;
                        }
                        else if (msg.RetryCount < 10)
                        {
                            txtime = 620;
                        }
                        else
                        {
                            txtime = 2000;
                        }

                        if ((now - msg.Last).TotalMilliseconds > txtime)
                        {
                            msg.Last = now;
                            msg.RetryCount++;
                            var rmsg = BinaryMessage.Make(ProtocolHandlerBase.MSG_REL)
                                       .UInt16(msg.Seq)
                                       .Byte(msg.Type)
                                       .Bytes(msg.Content)
                                       .Complete();
                            socket.Send(rmsg);
                            beat = false;
                        }
                    }
                }

                lock (thisLock)
                {
                    if (ackTime.HasValue && ((now - ackTime.Value).TotalMilliseconds >= AckThreshold))
                    {
                        socket.Send(BinaryMessage.Make(ProtocolHandlerBase.MSG_ACK).UInt16(ackSeq).Complete());
                        ackTime = null;
                        beat    = false;
                    }
                }

                if (beat)
                {
                    if ((now - last).TotalMilliseconds > KeepAliveTimeout)
                    {
                        socket.Send(BinaryMessage.Make(ProtocolHandlerBase.MSG_BEAT).Complete());
                        last = now;
                    }
                }
            }
        }