using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Threading; namespace BF { internal partial class TCPConnection : INetConnection { private INetChannel masterChannel; private NetIncomingMessage dnsErrorMessage = null; internal readonly NetConnectConfiguration configuration; public string UniqueIdentifier => configuration.UniqueIdentifier; public NetConnectStatus ConnectStatus { get { var status = masterChannel.ConnectStatus; return status; } } public IPEndPoint IpEndPoint { get { var ip = masterChannel.RemoteEndPoint; return ip; } } public long ServerTimestamp { get { var serverTimestamp = masterChannel.ServerTimestamp; return serverTimestamp; } } public TCPConnection(NetConnectConfiguration configuration) { this.configuration = configuration; waitingConnectChannels = new Dictionary(); verifyConnectedChannels = new List(); InitializeMessagePools(); } ~TCPConnection() { } public void Update() { FailedConnectedChannelUpdate(); ConnectedChannelUpdate(); WaitingConnectChannelUpdate(); VerifyConnectedChannelUpdate(); } public void Reconnect() { masterChannel?.Reconnect(); } public void Connect(string domainName, int port) { IPAddress[] targetAddressList = null; try { // TODO // targetAddressList = Dns.GetHostEntry(domainName).AddressList; targetAddressList = Dns.GetHostAddresses(domainName); } catch (SocketException socketException) { CreateDNSErrorMessage($"DNS parse domainName error : {socketException}"); return; } catch (Exception e) { CreateDNSErrorMessage($"DNS parse domainName error : {e}"); return; } if (targetAddressList == null || targetAddressList.Length <= 0) { CreateDNSErrorMessage($"DNS parse domainName error : address list is empty."); return; } foreach (IPAddress ip in targetAddressList) { ConnectInternal(ip, port); } } public void Connect(IPAddress ipAddress, int port) { ConnectInternal(ipAddress, port); } private void ConnectInternal(IPAddress ipAddress, int port) { bool isContains = waitingConnectChannels.ContainsKey(ipAddress); //already contains if (isContains) { return; } var remoteEndPoint = new IPEndPoint(ipAddress, port); var channel = new TCPChannel(this, remoteEndPoint); channel.Connect(ipAddress, port); waitingConnectChannels.Add(ipAddress, channel); //设置master channel SetMasterChannel(channel); } public void Close() { masterChannel?.Close(); masterChannel = null; if (waitingConnectChannels.Count <= 0) { return; } //clear all waiting connect channel foreach (var channel in waitingConnectChannels) { channel.Value.Close(); } waitingConnectChannels.Clear(); failedConnectedChannels.Clear(); } public INetOutgoingMessage CreateMessage() { INetOutgoingMessage message = CreateOutgoingMessage(NetOutgoingMessageType.UserData); return message; } public NetSendResult Send(INetOutgoingMessage message) { var result = masterChannel.Send(message); return result; } public NetSendResult Send(uint group, byte cmd, byte[] data) { var result = masterChannel.Send(group, cmd, data); return result; } public INetIncomingMessage ReadMessage() { INetIncomingMessage message = null; if (dnsErrorMessage != null) { message = dnsErrorMessage; dnsErrorMessage = null; return message; } message = masterChannel.ReadMessage(); return message; } public void RecycleMessage(INetIncomingMessage message) { Recycle((NetIncomingMessage)message); } } }