private void ConnectSingleIpAsync(string ip, [NotNull] TaskCompletionSource <IChannel> tcs, ICollection <string> candidateIps)
        {
            Task.Run(async() =>
            {
                bool socketAdopted      = false;
                var client              = new TcpClient();
                Action disposeTcpClient = () =>
                {
                    // ReSharper disable once AccessToModifiedClosure
                    if (socketAdopted)
                    {
                        return;
                    }

                    client?.Dispose();
                    client = null;
                    Env.Logger.Log($"clean up [{ip}]", nameof(ChannelManager));
                };

                try
                {
                    Env.Logger.Log($"Try to connect to [{ip}]", nameof(ChannelManager));
                    await client.ConnectAsync(ip, port); //这个耗时的过程不能取消,cancel token就没多大意义了。
                    if (!tcs.IsEnded() && client.Connected)
                    {
                        IPEndPoint remote = client.Client.RemoteEndPoint as IPEndPoint;
                        if (remote != null)
                        {
                            socketAdopted      = true;
                            TcpChannel channel = new TcpChannel(client)
                            {
                                IsInitiative = true,
                                RemoteIP     = remote.Address.ToString()
                            };
                            socketAdopted = tcs.TrySetResult(channel);
                            if (socketAdopted)
                            {
                                Env.Logger.Log($"Connected to [{ip}] successfully", nameof(ChannelManager));
                            }
                        }
                    }
                    //如果这个不成功,不要设置result,让别的连接尝试做这个工作。
                }
                catch (Exception e)
                {
                    //如果全都失败应该早点退出。
                    Env.Logger.Log($"Create TCP Client failed {ip} reason {e.Message}", nameof(ChannelManager));
                }
                finally
                {
                    if (!socketAdopted)
                    {
                        candidateIps.Remove(ip);
                        if (candidateIps.Count == 0)
                        {
                            tcs.TrySetResult(null);
                        }

                        disposeTcpClient();
                    }
                }
            });
        }
Example #2
0
        protected internal sealed override bool Process(ConversationMessage message)
        {
            switch (State)
            {
            case RequesterState.RequestRecovering:
                if (message is ConversationRecoverAgreedMessage)
                {
                    //对方同意恢复会话。
                    State = RequesterState.Running;
                    OnRecoverAgreed(message as ConversationRecoverAgreedMessage);
                    RecoverAgreed?.Invoke();
                }
                else if (message is ConversationRejectMessage)
                {
                    var rm = message as ConversationRejectMessage;
                    State = RequesterState.Rejected;
                    End();
                    OnRecoverRejected(rm);
                    RecoverRejected?.Invoke(rm.RejectCode);
                }
                else
                {
                    //对方再ConversationAgree或者Reject之前发来的消息,到底要不要处理?怎样才能保证对方不在我准备好之前发消息过来?
                    //其他消息,不理会。
                    OnMessageReceived(message);
                }
                break;

            case RequesterState.Requesting:
                if (message is ConversationAgreeMessage)
                {
                    WasAgreed = true;
                    State     = RequesterState.Running;
                    OnRequestAgreed(message as ConversationAgreeMessage);
                    Agreed?.Invoke();
                    if (!Response.IsEnded())
                    {
                        Response?.SetResult(message);
                    }
                    else
                    {
                        End();
                    }
                }
                else if (message is ConversationRejectMessage)
                {
                    if (!Response.IsEnded())
                    {
                        Response?.SetResult(message);
                    }
                    State = RequesterState.Rejected;
                    //终止此会话
                    End();
                    Rejected?.Invoke();
                }
                else
                {
                    //对方再ConversationAgree或者Reject之前发来的消息,到底要不要处理?怎样才能保证对方不在我准备好之前发消息过来?
                    //其他消息,不理会。
                    OnMessageReceived(message);
                }
                break;

            case RequesterState.Running:
                OnMessageReceived(message);
                break;
            }
            return(true);
        }