예제 #1
0
        private IEnumerator Run()
        {
            // Reconnection attempts so we don't hammer the system on failure.
            float        connectionPollTimeSec = 0.25f;
            TcpClient    socket       = null;
            PacketBuffer packetBuffer = new PacketBuffer(4 * 1024);

            System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
            ClientConnector connector          = null;

            while (!_quitFlag)
            {
                // First try establish a connection.
                while (!_quitFlag && !_connection.Connected)
                {
                    if (connector == null)
                    {
                        connector = new ClientConnector(_connection.EndPoint);
                    }

                    if (!connector.Connecting)
                    {
                        if (connector.Connected)
                        {
                            socket                = connector.Accept();
                            connector             = null;
                            _connection.Connected = true;
                            Status                = NetworkThreadStatus.Connected;
                            _currentFrame         = _totalFrames = 0u;
                            _packetQueue.Enqueue(BuildResetPacket());
                        }
                        else
                        {
                            connector.Abort();
                            connector = null;
                            if (!_connection.AutoReconnect)
                            {
                                // Failed connection and no auto reconnect.
                                Status = NetworkThreadStatus.ConnectionFailed;
                                break;
                            }
                        }
                    }

                    if (socket == null)
                    {
                        // Wait the timeout period before attempting to reconnect.
                        yield return(Workthread.CreateWait(connectionPollTimeSec));
                    }
                }

                timer.Start();
                // Read while connected.
                while (!_quitFlag && TcpClientUtil.Connected(socket))
                {
                    // We have a connection. Read messages while we can.
                    if (socket.Available > 0)
                    {
                        // Data available. Read from the network stream into a buffer and attempt to
                        // read a valid message.
                        packetBuffer.Append(socket.GetStream(), socket.Available);
                        PacketBuffer completedPacket;
                        bool         crcOk = true;
                        while ((completedPacket = packetBuffer.PopPacket(out crcOk)) != null || !crcOk)
                        {
                            if (crcOk)
                            {
                                // Decode and decompress collated packets. This will just return the same packet
                                // if not collated.
                                _collatedDecoder.SetPacket(completedPacket);
                                while ((completedPacket = _collatedDecoder.Next()) != null)
                                {
                                    if (completedPacket.Header.RoutingID == (ushort)RoutingID.Control)
                                    {
                                        ushort controlMessageId = completedPacket.Header.MessageID;
                                        if (controlMessageId == (ushort)ControlMessageID.EndFrame)
                                        {
                                            timer.Stop();
                                            FrameTime = timer.ElapsedMilliseconds * 1e-3f;
                                            timer.Reset();
                                            timer.Start();
                                            ++_currentFrame;
                                            ++_totalFrames;
                                        }
                                    }

                                    _packetQueue.Enqueue(completedPacket);
                                }
                            }
                            else
                            {
                                // TODO: Log CRC failure.
                            }
                        }
                    }
                    else
                    {
                        yield return(null);
                    }
                }

                // Disconnected.
                if (socket != null)
                {
                    socket.LingerState.Enabled = false;
                    socket.Close();
                    socket = null;
                }
                if (_connection.Connected)
                {
                    Status = NetworkThreadStatus.Disconnected;
                    _connection.Connected = false;
                }

                if (!_connection.AutoReconnect)
                {
                    break;
                }
                Status = NetworkThreadStatus.Reconnecting;
            }
        }
예제 #2
0
        private IEnumerator Run()
        {
            // Reconnection attempts so we don't hammer the system on failure.
            float        connectionPollTimeSec = 0.25f;
            TcpClient    socket       = null;
            PacketBuffer packetBuffer = new PacketBuffer(4 * 1024);

            System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
            ClientConnector connector          = null;

            while (!_quitFlag)
            {
                // First try establish a connection.
                while (!_quitFlag && !_connection.Connected)
                {
                    if (connector == null)
                    {
                        connector = new ClientConnector(_connection.EndPoint);
                    }

                    if (!connector.Connecting)
                    {
                        if (connector.Connected)
                        {
                            socket                = connector.Accept();
                            connector             = null;
                            _connection.Connected = true;
                            Status                = NetworkThreadStatus.Connected;
                            _currentFrame         = _totalFrames = 0u;
                            _packetQueue.Enqueue(BuildResetPacket());
                        }
                        else
                        {
                            connector.Abort();
                            connector = null;
                            if (!_connection.AutoReconnect)
                            {
                                // Failed connection and no auto reconnect.
                                Status = NetworkThreadStatus.ConnectionFailed;
                                break;
                            }
                        }
                    }

                    if (socket == null)
                    {
                        // Wait the timeout period before attempting to reconnect.
                        yield return(Workthread.CreateWait(connectionPollTimeSec));
                    }
                }

                timer.Start();
                // Read while connected.
                while (!_quitFlag && TcpClientUtil.Connected(socket))
                {
                    // We have a connection. Read messages while we can.
                    if (socket.Available > 0)
                    {
                        // Data available. Read from the network stream into a buffer and attempt to
                        // read a valid message.
                        packetBuffer.Append(socket.GetStream(), socket.Available);
                        PacketBuffer completedPacket;
                        bool         crcOk = true;
                        while ((completedPacket = packetBuffer.PopPacket(out crcOk)) != null || !crcOk)
                        {
                            if (crcOk)
                            {
                                // Decode and decompress collated packets. This will just return the same packet
                                // if not collated.
                                _collatedDecoder.SetPacket(completedPacket);
                                while ((completedPacket = _collatedDecoder.Next()) != null)
                                {
                                    if (completedPacket.Header.RoutingID == (ushort)RoutingID.Control)
                                    {
                                        ushort controlMessageId = completedPacket.Header.MessageID;
                                        if (controlMessageId == (ushort)ControlMessageID.EndFrame)
                                        {
                                            // Add a frame flush flag to every end frame message to ensure the render thread renders.
                                            // TODO: consider a way to frame skip in a live visualisation link.
                                            byte[] packetData   = completedPacket.Data;
                                            int    memberOffset = PacketHeader.Size + Marshal.OffsetOf(typeof(ControlMessage), "ControlFlags").ToInt32();
                                            uint   controlFlags = BitConverter.ToUInt32(packetData, memberOffset);
                                            controlFlags = Endian.FromNetwork(controlFlags);
                                            // Add the flush flag
                                            controlFlags |= (uint)EndFrameFlag.Flush;
                                            // Convert back to bytes and copy into the packet buffer.
                                            byte[] frameNumberBytes = BitConverter.GetBytes(Endian.ToNetwork(controlFlags));
                                            Array.Copy(frameNumberBytes, 0, packetData, memberOffset, frameNumberBytes.Length);
                                            // Recalculate the CRC as we've modified the packet.
                                            completedPacket.UpdateCrc();

                                            // Update the frame
                                            timer.Stop();
                                            FrameTime = timer.ElapsedMilliseconds * 1e-3f;
                                            timer.Reset();
                                            timer.Start();
                                            ++_currentFrame;
                                            ++_totalFrames;
                                        }
                                    }

                                    _packetQueue.Enqueue(completedPacket);
                                }
                            }
                            else
                            {
                                // TODO: Log CRC failure.
                            }
                        }
                    }
                    else
                    {
                        yield return(null);
                    }
                }

                // Disconnected.
                if (socket != null)
                {
                    socket.LingerState.Enabled = false;
                    socket.Close();
                    socket = null;
                }
                if (_connection.Connected)
                {
                    Status = NetworkThreadStatus.Disconnected;
                    _connection.Connected = false;
                }

                if (!_connection.AutoReconnect)
                {
                    break;
                }
                Status = NetworkThreadStatus.Reconnecting;
            }
        }