diff --git a/docs/README.md b/docs/README.md index 189dff2..ba44521 100644 --- a/docs/README.md +++ b/docs/README.md @@ -19,6 +19,10 @@ It is important to close the `c` object explicitly, via the `Close` method, when The class provides a number of other features explored in the following sections. +#### Connecting using IPv6 + +Connections default to using IPv4. Passing `IpVersionPreference` to the constructor can be used to specify whether IPv6 should be used. The DualStack option create a dual socket so both IPv4 and IPv6 will be tried on a connection, if the operating system supports it. + ### Connecting using UDS (Unix Domain Sockets) As an alternative to the standard TCP connection, kdb+ can use UDS. See [here](https://code.kx.com/q/basics/listening-port/#unix-domain-socket) for details. diff --git a/kx/c.cs b/kx/c.cs index f9fa017..d76de77 100644 --- a/kx/c.cs +++ b/kx/c.cs @@ -122,6 +122,43 @@ public class c : IDisposable /// private bool _isLittleEndian; + /// + /// Specifies the IP address family preference to use when establishing a TCP connection. + /// + /// + /// Use this option to control whether a connection should be attempted using IPv4, + /// IPv6, or a dual-mode socket that can support both IPv4 and IPv6 where the + /// operating system and network configuration allow it. + /// + public enum IpVersionPreference + { + /// + /// Use IPv4 only. + /// + /// + /// Creates or selects a socket that uses . + /// + IPv4, + + /// + /// Use IPv6 only. + /// + /// + /// Creates or selects a socket that uses + /// without accepting IPv4-mapped IPv6 addresses. + /// + IPv6, + + /// + /// Use a dual-mode socket that can support both IPv4 and IPv6. + /// + /// + /// Creates or selects an IPv6 socket with + /// enabled, allowing both IPv6 addresses and IPv4-mapped IPv6 addresses where supported. + /// + DualStack + } + /// /// Initialises a new instance of with a specified host and port /// to connect to. @@ -139,7 +176,8 @@ private c( string userPassword, int maxBufferSize, KdbTlsOptions tlsOptions, - bool uds) + bool uds, + IpVersionPreference ipVersionPreference) { if (host == null) { @@ -166,7 +204,18 @@ private c( } else { - _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + switch (ipVersionPreference) + { + case (IpVersionPreference.IPv4): + _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + break; + case (IpVersionPreference.IPv6): + _socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp); + break; + case (IpVersionPreference.DualStack): + _socket = new Socket(SocketType.Stream, ProtocolType.Tcp); + break; + } _socket.Connect(host, port); _isLoopback = _socket.RemoteEndPoint is IPEndPoint && IPAddress.IsLoopback((_socket.RemoteEndPoint as IPEndPoint).Address); @@ -216,6 +265,7 @@ private c( /// The username and passsword, as "username:password" for remote authorisation. /// The maximum buffer size, default is 65536. /// A boolean flag indicating whether or not TLS authentication is enabled, default is false. + /// The IP address family preference to use when establishing a TCP connection. /// or was null. /// must be between and /// Unable to connect to KDB+ process, access denied or process unavailable. @@ -224,8 +274,9 @@ public c( int port, string userPassword, int maxBufferSize = DefaultMaxBufferSize, - bool useTLS = false) - : this(host, port, userPassword, maxBufferSize, useTLS ? KdbTls.Default(host) : KdbTlsOptions.Disabled, false) + bool useTLS = false, + IpVersionPreference ipVersionPreference = IpVersionPreference.IPv4) + : this(host, port, userPassword, maxBufferSize, useTLS ? KdbTls.Default(host) : KdbTlsOptions.Disabled, false, ipVersionPreference) { } @@ -234,6 +285,7 @@ public c( /// The username/password string used for authentication. /// The maximum buffer size used for IPC messages. /// The TLS options to use for the connection. + /// The IP address family preference to use when establishing a TCP connection. /// /// or was null. /// @@ -249,8 +301,9 @@ public c( int port, string userPassword, int maxBufferSize, - KdbTlsOptions tlsOptions) - : this(host,port,userPassword,maxBufferSize,tlsOptions ?? KdbTlsOptions.Disabled,false) + KdbTlsOptions tlsOptions, + IpVersionPreference ipVersionPreference = IpVersionPreference.IPv4) + : this(host,port,userPassword,maxBufferSize,tlsOptions ?? KdbTlsOptions.Disabled,false,ipVersionPreference) { } @@ -262,14 +315,16 @@ public c( /// uds file e.g. "/tmp/kx.5010" is the default with kdb+ listening on port 5010 /// The username and passsword, as "username:password" for remote authorisation. /// The maximum buffer size, default is 65536. + /// The IP address family preference to use when establishing a TCP connection. /// or was null. /// Unable to connect to KDB+ process, access denied or process unavailable. /// The current OS does not support Unix Domain Sockets public c( string file, string userPassword, - int maxBufferSize = DefaultMaxBufferSize) - : this(file, 0, userPassword, maxBufferSize, KdbTlsOptions.Disabled, true) + int maxBufferSize = DefaultMaxBufferSize, + IpVersionPreference ipVersionPreference = IpVersionPreference.IPv4) + : this(file, 0, userPassword, maxBufferSize, KdbTlsOptions.Disabled, true, ipVersionPreference) { } @@ -281,6 +336,7 @@ public c( /// The username/password string used for authentication. /// The maximum buffer size used for IPC messages. /// The TLS options to use for the connection. + /// The IP address family preference to use when establishing a TCP connection. /// /// or was null. /// @@ -294,8 +350,9 @@ public c( string file, string userPassword, int maxBufferSize, - KdbTlsOptions tlsOptions) - : this(file, 0, userPassword, maxBufferSize, tlsOptions ?? KdbTlsOptions.Disabled, true) + KdbTlsOptions tlsOptions, + IpVersionPreference ipVersionPreference = IpVersionPreference.IPv4) + : this(file, 0, userPassword, maxBufferSize, tlsOptions ?? KdbTlsOptions.Disabled, true, ipVersionPreference) { }