예제 #1
0
            public bool SendHandshake(AeronHandshakeRequest handshakeRequest, int connectionResponseTimeoutMs)
            {
                using var handshakeRequestStream = new MemoryStream();
                Serializer.SerializeWithLengthPrefix(handshakeRequestStream, handshakeRequest, PrefixStyle.Base128);
                _buffer.Wrap(handshakeRequestStream.GetBuffer(), 0, (int)handshakeRequestStream.Length);

                var spinWait  = new SpinWait();
                var stopwatch = Stopwatch.StartNew();

                while (true)
                {
                    var errorCode = _publication.Offer(_buffer,
                                                       0,
                                                       (int)handshakeRequestStream.Length,
                                                       (buffer, offset, length) => (long)new AeronReservedValue(Utils.CurrentProtocolVersion,
                                                                                                                AeronMessageType.Connected,
                                                                                                                0));

                    if (errorCode == Publication.NOT_CONNECTED)
                    {
                        // This will happen as we just created the publication - we need to wait for Aeron to do its stuff

                        if (stopwatch.ElapsedMilliseconds > connectionResponseTimeoutMs)
                        {
                            _log.Error($"Failed to send handshake (not connected): {this}");
                            return(false);
                        }

                        spinWait.SpinOnce();
                        continue;
                    }

                    var result = Utils.InterpretPublicationOfferResult(errorCode);

                    if (result == AeronResultType.Success)
                    {
                        break;
                    }

                    if (result == AeronResultType.ShouldRetry)
                    {
                        spinWait.SpinOnce();
                        continue;
                    }

                    _log.Error($"Failed to send handshake: {this}");
                    return(false);
                }

                _buffer.Release();
                return(true);
            }
예제 #2
0
        public int Connect(string serverHost,
                           int serverPort,
                           Action onConnectedDelegate,
                           Action onDisconnectedDelegate,
                           AeronClientMessageReceivedHandler onMessageReceived,
                           int connectionResponseTimeoutMs)
        {
            if (serverHost == null)
            {
                throw new ArgumentNullException(nameof(serverHost));
            }

            if (_isTerminatedUnexpectedly)
            {
                return(-1);
            }

            string serverHostIp;

            if (serverHost.Equals("localhost", StringComparison.OrdinalIgnoreCase) || serverHost.Equals("127.0.0.1", StringComparison.OrdinalIgnoreCase))
            {
                // TODO IPC channel for local communication
                serverHostIp = "127.0.0.1";
            }
            else
            {
                var ipv4 =
                    Dns.GetHostEntry(serverHost).AddressList
                    .FirstOrDefault(x => x.AddressFamily == AddressFamily.InterNetwork)
                    ?? throw new ArgumentException($"Cannot resolve serverHost ip for {serverHost}");
                serverHostIp = ipv4.ToString();
            }

            var serverChannel = Utils.RemoteChannel(serverHostIp, serverPort);
            var publication   = _client.AddExclusivePublication(serverChannel, AeronServer.ServerStreamId);

            var localIp  = UdpUtils.GetLocalIPAddress(serverHostIp, serverPort);
            var streamId = MachineCounters.Instance.GetNewClientStreamId();

            GetChannelAndSubscription(localIp, streamId, out var clientChannel, out var subscription);

            var session = new AeronClientSession(this,
                                                 serverChannel,
                                                 publication,
                                                 subscription,
                                                 onConnectedDelegate,
                                                 onDisconnectedDelegate,
                                                 onMessageReceived);
            var connectionId = AddSession(session);

            _log.Info($"Connecting: {session}");

            var handshakeRequest = new AeronHandshakeRequest
            {
                Channel  = clientChannel,
                StreamId = streamId
            };

            if (!session.SendHandshake(handshakeRequest, connectionResponseTimeoutMs))
            {
                RemoveSession(session);
                session.Dispose();
                return(-1);
            }

            return(connectionId);
        }