diff --git a/Apewer/Network/TcpClient.cs b/Apewer/Network/TcpClient.cs index 425f722..74e0bca 100644 --- a/Apewer/Network/TcpClient.cs +++ b/Apewer/Network/TcpClient.cs @@ -24,19 +24,86 @@ namespace Apewer.Network public IPEndPoint RemoteEndPoint { get; private set; } /// 启动客户端,并连接到服务端。 - public TcpClient(string ip, int port) : this(IPAddress.Parse(ip), port) { } + /// 远程 IP 地址。 + /// 远程端口号。 + /// + /// + /// + public TcpClient(string ip, int port) : this(new IPEndPoint(IPAddress.Parse(ip), port), 0) { } /// 启动客户端,并连接到服务端。 - public TcpClient(IPAddress address, int port) : this(new IPEndPoint(address, port)) { } + /// 远程 IP 地址。 + /// 远程端口号。 + /// 连接超时毫秒数。当达到指定时长,或达到系统默认时长时,将会发生超时异常。 + /// + /// + /// + public TcpClient(string ip, int port, int timeout) : this(new IPEndPoint(IPAddress.Parse(ip), port), timeout) { } /// 启动客户端,并连接到服务端。 - public TcpClient(IPEndPoint endpoint) + /// 远程 IP 地址。 + /// 远程端口号。 + /// + /// + /// + public TcpClient(IPAddress ip, int port) : this(new IPEndPoint(ip, port), 0) { } + + /// 启动客户端,并连接到服务端。 + /// 远程 IP 地址。 + /// 远程端口号。 + /// 连接超时毫秒数。当达到指定时长,或达到系统默认时长时,将会发生超时异常。 + /// + /// + /// + public TcpClient(IPAddress ip, int port, int timeout) : this(new IPEndPoint(ip, port), timeout) { } + + /// 启动客户端,并连接到服务端。 + public TcpClient(IPEndPoint endpoint) : this(endpoint, 0) { } + + /// 启动客户端,并连接到服务端。 + /// 远程终结点。 + /// 连接超时毫秒数。当达到指定时长,或达到系统默认时长时,将会发生超时异常。 + /// + /// + /// + public TcpClient(IPEndPoint endpoint, int timeout) { + if (endpoint == null) throw new ArgumentNullException(nameof(endpoint)); + if (timeout < 1) throw new ArgumentOutOfRangeException(nameof(timeout)); + _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - _socket.Connect(endpoint); - _socket.SendTimeout = 5000; - LocalEndPoint = _socket.LocalEndPoint as IPEndPoint; - RemoteEndPoint = endpoint; + if (timeout > 0) + { + RuntimeUtility.InBackground(timeout, () => + { + if (!_socket.Connected) + { + _socket.Close(); +#if !NET20 + _socket.Dispose(); +#endif + } + }, true); + } + try + { + _socket.Connect(endpoint); + _socket.SendTimeout = 5000; + LocalEndPoint = _socket.LocalEndPoint as IPEndPoint; + RemoteEndPoint = endpoint; + } + catch (SocketException ex) + { + if (ex.SocketErrorCode == SocketError.NotSocket) + { + throw new SocketException((int)SocketError.TimedOut); + } + throw new Exception($"{ex.ErrorCode} {ex.SocketErrorCode}: {ex.Message}"); + } + catch + { + throw; + } } /// 关闭连接,释放系统资源。