示例#1
0
        private void GetChannelAndSubscription(string localIp,
                                               int streamId,
                                               out string clientChannel,
                                               out Subscription subscription)
        {
            // Finding port for the first time is slow and in tests with
            // parallel connections many clients have different ports.
            // Simple lock is needed.
            lock (_connectionsLock)
            {
                while (true)
                {
                    if (_clientPort == 0)
                    {
                        var clientPort = 0;
                        while (true)
                        {
                            try
                            {
                                clientPort    = UdpUtils.GetRandomUnusedPort();
                                clientChannel = Utils.RemoteChannel(localIp, clientPort);
                                subscription  = _client.AddSubscription(clientChannel, streamId);
                                break;
                            }
                            catch (RegistrationException ex)
                            {
                                // if port was already reused by someone
                                _log.Warn($"Could not subscribe on new port {clientPort}", ex);
                            }
                        }

                        _clientPort = clientPort;
                        return;
                    }

                    try
                    {
                        clientChannel = Utils.RemoteChannel(localIp, _clientPort);
                        subscription  = _client.AddSubscription(clientChannel, streamId);
                        return;
                    }
                    catch (RegistrationException ex)
                    {
                        _log.Warn($"Could not subscribe on existing port {_clientPort}", ex);
                        _clientPort = 0;
                    }
                }
            }
        }
示例#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);
        }