From 1c4add8d9b8213543bd1bab56f8491bfbb025262 Mon Sep 17 00:00:00 2001 From: Christoph Bauer Date: Fri, 11 Apr 2025 16:05:31 +0200 Subject: [PATCH 1/4] Tcp Keepalive for Linux (NET8.0) New Target .NET 8.0 Fixes setup of Tcp Keepalive under Linux --- src/NetMQ.Tests/ClientServer.cs | 2 +- src/NetMQ/Annotations.cs | 2 +- src/NetMQ/AsyncReceiveExtensions.cs | 2 +- .../Core/Mechanisms/CurveClientMechanism.cs | 2 +- .../Core/Mechanisms/CurveServerMechanism.cs | 4 +- src/NetMQ/Core/Transports/Pgm/PgmSocket.cs | 2 +- src/NetMQ/Core/Transports/Tcp/TcpConnector.cs | 8 ++ src/NetMQ/Core/Transports/Tcp/TcpListener.cs | 108 ++++++++++-------- src/NetMQ/Core/Utils/OpCode.cs | 2 +- src/NetMQ/Core/Utils/SpanUtility.cs | 2 +- src/NetMQ/GroupSocketExtensions.cs | 4 +- src/NetMQ/NetMQ.csproj | 10 +- src/NetMQ/NetMQRuntime.cs | 2 +- src/NetMQ/NetMQSocket.cs | 6 +- .../ReceiveThreadSafeSocketExtensions.cs | 4 +- src/NetMQ/RoutingIdSocketExtensions.cs | 4 +- src/NetMQ/ThreadSafeSocket.cs | 2 +- src/NetMQ/Utils/EncodingExtensions.cs | 2 +- .../NetMQ.SimpleTests.csproj | 2 +- src/Performance/local_lat/local_lat.csproj | 2 +- src/Performance/local_thr/local_thr.csproj | 2 +- src/Performance/remote_lat/remote_lat.csproj | 2 +- src/Performance/remote_thr/remote_thr.csproj | 2 +- 23 files changed, 95 insertions(+), 83 deletions(-) diff --git a/src/NetMQ.Tests/ClientServer.cs b/src/NetMQ.Tests/ClientServer.cs index 8fad5621d..a6e1ee0d5 100644 --- a/src/NetMQ.Tests/ClientServer.cs +++ b/src/NetMQ.Tests/ClientServer.cs @@ -82,7 +82,7 @@ public async void AsyncWithCancellationToken() await Assert.ThrowsAnyAsync(async () => await server.ReceiveStringAsync(source.Token)); } -#if NETCOREAPP3_1 +#if NET8_0_OR_GREATER [Fact(Timeout = 120)] public async void AsyncEnumerableCanceled() diff --git a/src/NetMQ/Annotations.cs b/src/NetMQ/Annotations.cs index 90e761655..be677e68b 100644 --- a/src/NetMQ/Annotations.cs +++ b/src/NetMQ/Annotations.cs @@ -1,6 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE.md file in the project root for more information. -#if !NETSTANDARD2_1 +#if !NETSTANDARD2_1 && !NET8_0_OR_GREATER namespace System.Diagnostics.CodeAnalysis { diff --git a/src/NetMQ/AsyncReceiveExtensions.cs b/src/NetMQ/AsyncReceiveExtensions.cs index 10c122021..f7ddfe276 100644 --- a/src/NetMQ/AsyncReceiveExtensions.cs +++ b/src/NetMQ/AsyncReceiveExtensions.cs @@ -1,4 +1,4 @@ -#if NETSTANDARD2_0 || NETSTANDARD2_1 || NET47 +#if NET8_0_OR_GREATER || NET8_0_OR_GREATER || NETSTANDARD2_0 || NETSTANDARD2_1 || NET47 using System; using System.Collections.Generic; diff --git a/src/NetMQ/Core/Mechanisms/CurveClientMechanism.cs b/src/NetMQ/Core/Mechanisms/CurveClientMechanism.cs index 5715952b7..75a677a6b 100644 --- a/src/NetMQ/Core/Mechanisms/CurveClientMechanism.cs +++ b/src/NetMQ/Core/Mechanisms/CurveClientMechanism.cs @@ -189,7 +189,7 @@ PullMsgResult ProduceInitiate(ref Msg msg) VouchNoncePrefix.CopyTo(vouchNonce); using var rng = RandomNumberGenerator.Create(); -#if NETSTANDARD2_1 +#if NET8_0_OR_GREATER || NETSTANDARD2_1 rng.GetBytes(vouchNonce.Slice(8)); #else byte[] temp = new byte[16]; diff --git a/src/NetMQ/Core/Mechanisms/CurveServerMechanism.cs b/src/NetMQ/Core/Mechanisms/CurveServerMechanism.cs index 1a104867b..a3747aaa2 100644 --- a/src/NetMQ/Core/Mechanisms/CurveServerMechanism.cs +++ b/src/NetMQ/Core/Mechanisms/CurveServerMechanism.cs @@ -157,7 +157,7 @@ PullMsgResult ProduceWelcome(ref Msg msg) // 8-byte prefix plus 16-byte random nonce CookieNoncePrefix.CopyTo(cookieNonce); using var rng = RandomNumberGenerator.Create(); -#if NETSTANDARD2_1 +#if NET8_0_OR_GREATER || NETSTANDARD2_1 rng.GetBytes(cookieNonce.Slice(8)); #else byte[] temp = new byte[16]; @@ -184,7 +184,7 @@ PullMsgResult ProduceWelcome(ref Msg msg) // Create full nonce for encryption // 8-byte prefix plus 16-byte random nonce WelcomeNoncePrefix.CopyTo(welcomeNonce); -#if NETSTANDARD2_1 +#if NET8_0_OR_GREATER || NETSTANDARD2_1 rng.GetBytes(welcomeNonce.Slice(8)); #else rng.GetBytes(temp); diff --git a/src/NetMQ/Core/Transports/Pgm/PgmSocket.cs b/src/NetMQ/Core/Transports/Pgm/PgmSocket.cs index e0a2713da..c2440cbb1 100644 --- a/src/NetMQ/Core/Transports/Pgm/PgmSocket.cs +++ b/src/NetMQ/Core/Transports/Pgm/PgmSocket.cs @@ -97,7 +97,7 @@ internal void Init() Debug.WriteLine(xMsg); // If running on Microsoft Windows, suggest to the developer that he may need to install MSMQ in order to get PGM socket support. -#if NETSTANDARD1_1_OR_GREATER +#if NET8_0_OR_GREATER || NETSTANDARD1_1_OR_GREATER bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); #else bool isWindows = true; diff --git a/src/NetMQ/Core/Transports/Tcp/TcpConnector.cs b/src/NetMQ/Core/Transports/Tcp/TcpConnector.cs index 63bda2cad..c3f03e909 100755 --- a/src/NetMQ/Core/Transports/Tcp/TcpConnector.cs +++ b/src/NetMQ/Core/Transports/Tcp/TcpConnector.cs @@ -248,6 +248,13 @@ public void OutCompleted(SocketError socketError, int bytesTransferred) // Set the TCP keep-alive option values to the underlying socket. m_s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, m_options.TcpKeepalive); + +#if NET8_0_OR_GREATER + if (m_options.TcpKeepaliveIdle != -1) + m_s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveTime, m_options.TcpKeepaliveIdle / 1000); + if (m_options.TcpKeepaliveIntvl != -1) + m_s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, m_options.TcpKeepaliveIntvl / 1000); +#else if (m_options.TcpKeepaliveIdle != -1 && m_options.TcpKeepaliveIntvl != -1) { // Write the TCP keep-alive options to a byte-array, to feed to the IOControl method.. @@ -261,6 +268,7 @@ public void OutCompleted(SocketError socketError, int bytesTransferred) m_s.IOControl(IOControlCode.KeepAliveValues, (byte[])bytes, null); } +#endif } // Create the engine object for this connection. diff --git a/src/NetMQ/Core/Transports/Tcp/TcpListener.cs b/src/NetMQ/Core/Transports/Tcp/TcpListener.cs index 98b8261a5..c9e8efd4e 100644 --- a/src/NetMQ/Core/Transports/Tcp/TcpListener.cs +++ b/src/NetMQ/Core/Transports/Tcp/TcpListener.cs @@ -22,7 +22,7 @@ You should have received a copy of the GNU Lesser General Public License using System; using System.Diagnostics; using System.Net.Sockets; -#if NETSTANDARD2_0 || NETSTANDARD2_1 +#if NET8_0_OR_GREATER || NETSTANDARD2_0 || NETSTANDARD2_1 using System.Runtime.InteropServices; #endif using AsyncIO; @@ -45,12 +45,12 @@ internal class TcpListener : Own, IProactorEvents /// private AsyncSocket? m_handle; -/* - /// - /// socket being accepted - /// - private AsyncSocket m_acceptedSocket; -*/ + /* + /// + /// socket being accepted + /// + private AsyncSocket m_acceptedSocket; + */ /// /// Socket the listener belongs to. @@ -107,7 +107,7 @@ protected override void ProcessPlug() protected override void ProcessTerm(int linger) { Assumes.NotNull(m_handle); - + m_ioObject.SetHandler(this); m_ioObject.RemoveSocket(m_handle); Close(); @@ -141,7 +141,7 @@ public virtual void SetAddress(string addr) } } -#if NETSTANDARD2_0 || NETSTANDARD2_1 +#if NET8_0_OR_GREATER || NETSTANDARD2_0 || NETSTANDARD2_1 // This command is failing on linux if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) m_handle.ExclusiveAddressUse = false; @@ -194,68 +194,76 @@ public void InCompleted(SocketError socketError, int bytesTransferred) switch (socketError) { case SocketError.Success: - { - // TODO: check TcpFilters - var acceptedSocket = m_handle.GetAcceptedSocket(); + { + // TODO: check TcpFilters + var acceptedSocket = m_handle.GetAcceptedSocket(); acceptedSocket.NoDelay = true; - if (m_options.TcpKeepalive != -1) - { - acceptedSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, m_options.TcpKeepalive); - - if (m_options.TcpKeepaliveIdle != -1 && m_options.TcpKeepaliveIntvl != -1) + if (m_options.TcpKeepalive != -1) { - var bytes = new ByteArraySegment(new byte[12]); + acceptedSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, m_options.TcpKeepalive); +#if NET8_0_OR_GREATER + if (m_options.TcpKeepaliveIdle != -1) + acceptedSocket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveTime, m_options.TcpKeepaliveIdle / 1000); + if (m_options.TcpKeepaliveIntvl != -1) + acceptedSocket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, m_options.TcpKeepaliveIntvl / 1000); +#else + + if (m_options.TcpKeepaliveIdle != -1 && m_options.TcpKeepaliveIntvl != -1) + { + var bytes = new ByteArraySegment(new byte[12]); + + Endianness endian = BitConverter.IsLittleEndian ? Endianness.Little : Endianness.Big; - Endianness endian = BitConverter.IsLittleEndian ? Endianness.Little : Endianness.Big; + bytes.PutInteger(endian, m_options.TcpKeepalive, 0); + bytes.PutInteger(endian, m_options.TcpKeepaliveIdle, 4); + bytes.PutInteger(endian, m_options.TcpKeepaliveIntvl, 8); - bytes.PutInteger(endian, m_options.TcpKeepalive, 0); - bytes.PutInteger(endian, m_options.TcpKeepaliveIdle, 4); - bytes.PutInteger(endian, m_options.TcpKeepaliveIntvl, 8); + acceptedSocket.IOControl(IOControlCode.KeepAliveValues, (byte[])bytes, null); + } +#endif - acceptedSocket.IOControl(IOControlCode.KeepAliveValues, (byte[])bytes, null); } - } - // Create the engine object for this connection. - var engine = new StreamEngine(acceptedSocket, m_options, m_endpoint); + // Create the engine object for this connection. + var engine = new StreamEngine(acceptedSocket, m_options, m_endpoint); - // Choose I/O thread to run connector in. Given that we are already - // running in an I/O thread, there must be at least one available. - IOThread? ioThread = ChooseIOThread(m_options.Affinity); + // Choose I/O thread to run connector in. Given that we are already + // running in an I/O thread, there must be at least one available. + IOThread? ioThread = ChooseIOThread(m_options.Affinity); - Assumes.NotNull(ioThread); + Assumes.NotNull(ioThread); - // Create and launch a session object. - // TODO: send null in address parameter, is unneeded in this case - SessionBase session = SessionBase.Create(ioThread, false, m_socket, m_options, new Address(m_handle.LocalEndPoint)); - session.IncSeqnum(); - LaunchChild(session); + // Create and launch a session object. + // TODO: send null in address parameter, is unneeded in this case + SessionBase session = SessionBase.Create(ioThread, false, m_socket, m_options, new Address(m_handle.LocalEndPoint)); + session.IncSeqnum(); + LaunchChild(session); - SendAttach(session, engine, false); + SendAttach(session, engine, false); - m_socket.EventAccepted(m_endpoint, acceptedSocket); + m_socket.EventAccepted(m_endpoint, acceptedSocket); - Accept(); - break; - } + Accept(); + break; + } case SocketError.ConnectionReset: case SocketError.NoBufferSpaceAvailable: case SocketError.TooManyOpenSockets: - { - m_socket.EventAcceptFailed(m_endpoint, socketError.ToErrorCode()); + { + m_socket.EventAcceptFailed(m_endpoint, socketError.ToErrorCode()); - Accept(); - break; - } + Accept(); + break; + } default: - { - NetMQException exception = NetMQException.Create(socketError); + { + NetMQException exception = NetMQException.Create(socketError); - m_socket.EventAcceptFailed(m_endpoint, exception.ErrorCode); - throw exception; - } + m_socket.EventAcceptFailed(m_endpoint, exception.ErrorCode); + throw exception; + } } } diff --git a/src/NetMQ/Core/Utils/OpCode.cs b/src/NetMQ/Core/Utils/OpCode.cs index 060064c60..64b9daa6f 100644 --- a/src/NetMQ/Core/Utils/OpCode.cs +++ b/src/NetMQ/Core/Utils/OpCode.cs @@ -20,7 +20,7 @@ public static bool Open() string val = Environment.GetEnvironmentVariable("NETQM_SUPPRESS_RDTSC"); if (!string.IsNullOrEmpty(val)) return false; -#if NETSTANDARD1_1_OR_GREATER || NET471_OR_GREATER +#if NET8_0_OR_GREATER || NETSTANDARD1_1_OR_GREATER || NET471_OR_GREATER if (RuntimeInformation.ProcessArchitecture != Architecture.X86 && RuntimeInformation.ProcessArchitecture != Architecture.X64) { diff --git a/src/NetMQ/Core/Utils/SpanUtility.cs b/src/NetMQ/Core/Utils/SpanUtility.cs index a5c529d30..61b646f72 100644 --- a/src/NetMQ/Core/Utils/SpanUtility.cs +++ b/src/NetMQ/Core/Utils/SpanUtility.cs @@ -7,7 +7,7 @@ internal static class SpanUtility { public static string ToAscii(Span bytes) { -#if NETSTANDARD2_1 +#if NET8_0_OR_GREATER || NETSTANDARD2_1 return Encoding.ASCII.GetString(bytes); #else return Encoding.ASCII.GetString(bytes.ToArray()); diff --git a/src/NetMQ/GroupSocketExtensions.cs b/src/NetMQ/GroupSocketExtensions.cs index f4c305502..7ce42202e 100644 --- a/src/NetMQ/GroupSocketExtensions.cs +++ b/src/NetMQ/GroupSocketExtensions.cs @@ -376,7 +376,7 @@ public static bool TryReceiveBytes(this IGroupInSocket socket, TimeSpan timeout, #region AsyncEnumerable -#if NETSTANDARD2_1 +#if NET8_0_OR_GREATER || NETSTANDARD2_1 /// /// Provides a consuming IAsyncEnumerable for receiving messages from the socket. /// @@ -575,7 +575,7 @@ public static bool TryReceiveString(this IGroupInSocket socket, TimeSpan timeout #region AsyncEnumerable -#if NETSTANDARD2_1 +#if NET8_0_OR_GREATER || NETSTANDARD2_1 /// /// Provides a consuming IAsyncEnumerable for receiving messages from the socket. /// diff --git a/src/NetMQ/NetMQ.csproj b/src/NetMQ/NetMQ.csproj index 788c2879c..65115f1be 100644 --- a/src/NetMQ/NetMQ.csproj +++ b/src/NetMQ/NetMQ.csproj @@ -3,7 +3,7 @@ A 100% native C# port of the lightweight high performance messaging library ZeroMQ 4.0.0.0 - net47;netstandard2.1 + net47;netstandard21;net8.0 portable ./NetMQ.snk true @@ -38,12 +38,8 @@ - - - - - - + + diff --git a/src/NetMQ/NetMQRuntime.cs b/src/NetMQ/NetMQRuntime.cs index 87748a31c..09162ce85 100644 --- a/src/NetMQ/NetMQRuntime.cs +++ b/src/NetMQ/NetMQRuntime.cs @@ -1,4 +1,4 @@ -#if NETSTANDARD2_0 || NETSTANDARD2_1 || NET47 +#if NET8_0_OR_GREATER || NETSTANDARD2_0 || NETSTANDARD2_1 || NET47 using System; using System.Threading; diff --git a/src/NetMQ/NetMQSocket.cs b/src/NetMQ/NetMQSocket.cs index 05a52ccbd..238b48210 100644 --- a/src/NetMQ/NetMQSocket.cs +++ b/src/NetMQ/NetMQSocket.cs @@ -25,7 +25,7 @@ public abstract class NetMQSocket : INetMQSocket private EventHandler? m_sendReady; private int m_isClosed; - #if NETSTANDARD2_0 || NETSTANDARD2_1 || NET47 + #if NET8_0_OR_GREATER || NETSTANDARD2_0 || NETSTANDARD2_1 || NET47 private NetMQRuntime? m_runtime; #endif @@ -249,7 +249,7 @@ public void Unbind(string address) /// Closes this socket, rendering it unusable. Equivalent to calling . public void Close() { - #if NETSTANDARD2_0 || NETSTANDARD2_1 || NET47 + #if NET8_0_OR_GREATER || NETSTANDARD2_0 || NETSTANDARD2_1 || NET47 if (m_runtime != null) { m_runtime.Remove(this); @@ -391,7 +391,7 @@ public virtual bool TrySend(ref Msg msg, TimeSpan timeout, bool more) #endregion - #if NETSTANDARD2_0 || NETSTANDARD2_1 || NET47 + #if NET8_0_OR_GREATER || NETSTANDARD2_0 || NETSTANDARD2_1 || NET47 internal void AttachToRuntime() { diff --git a/src/NetMQ/ReceiveThreadSafeSocketExtensions.cs b/src/NetMQ/ReceiveThreadSafeSocketExtensions.cs index d0a163e86..73380b464 100644 --- a/src/NetMQ/ReceiveThreadSafeSocketExtensions.cs +++ b/src/NetMQ/ReceiveThreadSafeSocketExtensions.cs @@ -119,7 +119,7 @@ public static ValueTask ReceiveBytesAsync(this IThreadSafeInSocket socke #region AsyncEnumerable -#if NETSTANDARD2_1 +#if NET8_0_OR_GREATER || NETSTANDARD2_1 /// /// Provides a consuming IAsyncEnumerable for receiving messages from the socket. @@ -302,7 +302,7 @@ public static ValueTask ReceiveStringAsync(this IThreadSafeInSocket sock #region AsyncEnumerable -#if NETSTANDARD2_1 +#if NET8_0_OR_GREATER || NETSTANDARD2_1 /// /// Provides a consuming IAsyncEnumerable for receiving messages from the socket. diff --git a/src/NetMQ/RoutingIdSocketExtensions.cs b/src/NetMQ/RoutingIdSocketExtensions.cs index 6aaac857a..e2e260ecb 100644 --- a/src/NetMQ/RoutingIdSocketExtensions.cs +++ b/src/NetMQ/RoutingIdSocketExtensions.cs @@ -372,7 +372,7 @@ public static bool TryReceiveBytes(this IRoutingIdSocket socket, TimeSpan timeou #region AsyncEnumerable -#if NETSTANDARD2_1 +#if NET8_0_OR_GREATER || NETSTANDARD2_1 /// /// Provides a consuming IAsyncEnumerable for receiving messages from the socket. @@ -564,7 +564,7 @@ public static bool TryReceiveString(this IRoutingIdSocket socket, TimeSpan timeo #region AsyncEnumerable -#if NETSTANDARD2_1 +#if NET8_0_OR_GREATER || NETSTANDARD2_1 /// /// Provides a consuming IAsyncEnumerable for receiving messages from the socket. diff --git a/src/NetMQ/ThreadSafeSocket.cs b/src/NetMQ/ThreadSafeSocket.cs index b0d5b7f19..14611ff18 100644 --- a/src/NetMQ/ThreadSafeSocket.cs +++ b/src/NetMQ/ThreadSafeSocket.cs @@ -200,7 +200,7 @@ public void Unbind(string address) /// Closes this socket, rendering it unusable. Equivalent to calling . public void Close() { - // #if NETSTANDARD2_0 || NETSTANDARD2_1 || NET47 + // #if NET8_0_OR_GREATER || NETSTANDARD2_0 || NETSTANDARD2_1 || NET47 // if (m_runtime != null) // { // m_runtime.Remove(this); diff --git a/src/NetMQ/Utils/EncodingExtensions.cs b/src/NetMQ/Utils/EncodingExtensions.cs index 059ed556b..c5e821276 100644 --- a/src/NetMQ/Utils/EncodingExtensions.cs +++ b/src/NetMQ/Utils/EncodingExtensions.cs @@ -1,4 +1,4 @@ -#if !NETSTANDARD2_1 +#if !NETSTANDARD2_1 && !NET8_0_OR_GREATER using System; using System.Text; diff --git a/src/Performance/NetMQ.SimpleTests/NetMQ.SimpleTests.csproj b/src/Performance/NetMQ.SimpleTests/NetMQ.SimpleTests.csproj index d3810f061..5af3b129e 100644 --- a/src/Performance/NetMQ.SimpleTests/NetMQ.SimpleTests.csproj +++ b/src/Performance/NetMQ.SimpleTests/NetMQ.SimpleTests.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 Exe diff --git a/src/Performance/local_lat/local_lat.csproj b/src/Performance/local_lat/local_lat.csproj index d3810f061..5af3b129e 100644 --- a/src/Performance/local_lat/local_lat.csproj +++ b/src/Performance/local_lat/local_lat.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 Exe diff --git a/src/Performance/local_thr/local_thr.csproj b/src/Performance/local_thr/local_thr.csproj index d3810f061..5af3b129e 100644 --- a/src/Performance/local_thr/local_thr.csproj +++ b/src/Performance/local_thr/local_thr.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 Exe diff --git a/src/Performance/remote_lat/remote_lat.csproj b/src/Performance/remote_lat/remote_lat.csproj index 9c8142a46..0b65ce6cb 100644 --- a/src/Performance/remote_lat/remote_lat.csproj +++ b/src/Performance/remote_lat/remote_lat.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 Exe diff --git a/src/Performance/remote_thr/remote_thr.csproj b/src/Performance/remote_thr/remote_thr.csproj index d3810f061..4d621a360 100644 --- a/src/Performance/remote_thr/remote_thr.csproj +++ b/src/Performance/remote_thr/remote_thr.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.09 Exe From a3b40e1bd2462491d8f63d384f7075a1de85ff3a Mon Sep 17 00:00:00 2001 From: Christoph Bauer Date: Wed, 16 Apr 2025 14:01:40 +0200 Subject: [PATCH 2/4] Add TcpKeepaliveCnt --- src/NetMQ.Tests/SocketOptionsTests.cs | 4 ++-- src/NetMQ/Core/Options.cs | 7 ++++++ src/NetMQ/Core/Transports/Tcp/TcpConnector.cs | 22 +++++++++++-------- src/NetMQ/Core/Transports/Tcp/TcpListener.cs | 5 ++++- src/NetMQ/Core/ZmqSocketOption.cs | 5 +++++ src/NetMQ/NetMQ.csproj | 2 ++ src/NetMQ/SocketOptions.cs | 12 ++++++++++ 7 files changed, 45 insertions(+), 12 deletions(-) mode change 100755 => 100644 src/NetMQ/Core/Transports/Tcp/TcpConnector.cs diff --git a/src/NetMQ.Tests/SocketOptionsTests.cs b/src/NetMQ.Tests/SocketOptionsTests.cs index 4ced4c229..3626f24ff 100644 --- a/src/NetMQ.Tests/SocketOptionsTests.cs +++ b/src/NetMQ.Tests/SocketOptionsTests.cs @@ -77,8 +77,8 @@ public void GetAndSetAllProperties() socket.Options.TcpKeepalive = true; Assert.True(socket.Options.TcpKeepalive); -// socket.Options.TcpKeepaliveCnt = 100; -// Assert.Equal(100, socket.Options.TcpKeepaliveCnt); + socket.Options.TcpKeepaliveCnt = 100; + Assert.Equal(100, socket.Options.TcpKeepaliveCnt); socket.Options.TcpKeepaliveIdle = TimeSpan.FromMilliseconds(100); Assert.Equal(TimeSpan.FromMilliseconds(100), socket.Options.TcpKeepaliveIdle); diff --git a/src/NetMQ/Core/Options.cs b/src/NetMQ/Core/Options.cs index 673184055..be11b9483 100644 --- a/src/NetMQ/Core/Options.cs +++ b/src/NetMQ/Core/Options.cs @@ -439,6 +439,10 @@ public void SetSocketOption(ZmqSocketOption option, object? optionValue) TcpKeepalive = tcpKeepalive; break; + case ZmqSocketOption.TcpKeepaliveCnt: + TcpKeepaliveCnt = Get(); + break; + case ZmqSocketOption.DelayAttachOnConnect: DelayAttachOnConnect = Get(); break; @@ -615,6 +619,9 @@ public void SetSocketOption(ZmqSocketOption option, object? optionValue) case ZmqSocketOption.TcpKeepalive: return TcpKeepalive; + case ZmqSocketOption.TcpKeepaliveCnt: + return TcpKeepaliveCnt; + case ZmqSocketOption.DelayAttachOnConnect: return DelayAttachOnConnect; diff --git a/src/NetMQ/Core/Transports/Tcp/TcpConnector.cs b/src/NetMQ/Core/Transports/Tcp/TcpConnector.cs old mode 100755 new mode 100644 index c3f03e909..114384750 --- a/src/NetMQ/Core/Transports/Tcp/TcpConnector.cs +++ b/src/NetMQ/Core/Transports/Tcp/TcpConnector.cs @@ -206,7 +206,7 @@ private void StartConnecting() // TerminatingException can occur in above call to EventConnectDelayed via // MonitorEvent.Write if corresponding PairSocket has been sent Term command catch (TerminatingException) - {} + { } } /// @@ -236,9 +236,12 @@ public void OutCompleted(SocketError socketError, int bytesTransferred) m_ioObject.RemoveSocket(m_s); m_handleValid = false; - try { + try + { m_s.NoDelay = true; - } catch (ArgumentException) { + } + catch (ArgumentException) + { // OSX sometime fail while the socket is still connecting } @@ -248,12 +251,13 @@ public void OutCompleted(SocketError socketError, int bytesTransferred) // Set the TCP keep-alive option values to the underlying socket. m_s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, m_options.TcpKeepalive); - -#if NET8_0_OR_GREATER - if (m_options.TcpKeepaliveIdle != -1) - m_s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveTime, m_options.TcpKeepaliveIdle / 1000); - if (m_options.TcpKeepaliveIntvl != -1) - m_s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, m_options.TcpKeepaliveIntvl / 1000); +#if NETCOREAPP3_1_OR_GREATER + if (m_options.TcpKeepaliveIdle != -1) + m_s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveTime, m_options.TcpKeepaliveIdle / 1000); + if (m_options.TcpKeepaliveIntvl != -1) + m_s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, m_options.TcpKeepaliveIntvl / 1000); + if (m_options.TcpKeepaliveCnt != -1) + m_s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveRetryCount, m_options.TcpKeepaliveCnt); #else if (m_options.TcpKeepaliveIdle != -1 && m_options.TcpKeepaliveIntvl != -1) { diff --git a/src/NetMQ/Core/Transports/Tcp/TcpListener.cs b/src/NetMQ/Core/Transports/Tcp/TcpListener.cs index c9e8efd4e..d38c2ce3b 100644 --- a/src/NetMQ/Core/Transports/Tcp/TcpListener.cs +++ b/src/NetMQ/Core/Transports/Tcp/TcpListener.cs @@ -203,11 +203,13 @@ public void InCompleted(SocketError socketError, int bytesTransferred) if (m_options.TcpKeepalive != -1) { acceptedSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, m_options.TcpKeepalive); -#if NET8_0_OR_GREATER +#if NETCOREAPP3_1_OR_GREATER if (m_options.TcpKeepaliveIdle != -1) acceptedSocket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveTime, m_options.TcpKeepaliveIdle / 1000); if (m_options.TcpKeepaliveIntvl != -1) acceptedSocket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, m_options.TcpKeepaliveIntvl / 1000); + if (m_options.TcpKeepaliveCnt != -1) + acceptedSocket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveRetryCount, m_options.TcpKeepaliveCnt); #else if (m_options.TcpKeepaliveIdle != -1 && m_options.TcpKeepaliveIntvl != -1) @@ -247,6 +249,7 @@ public void InCompleted(SocketError socketError, int bytesTransferred) Accept(); break; + } case SocketError.ConnectionReset: case SocketError.NoBufferSpaceAvailable: diff --git a/src/NetMQ/Core/ZmqSocketOption.cs b/src/NetMQ/Core/ZmqSocketOption.cs index 9cbfd49a0..97a1a446d 100644 --- a/src/NetMQ/Core/ZmqSocketOption.cs +++ b/src/NetMQ/Core/ZmqSocketOption.cs @@ -199,6 +199,11 @@ internal enum ZmqSocketOption /// TcpKeepalive = 34, + /// + /// Set TCP keep alive retry count + /// + TcpKeepaliveCnt = 35, + /// /// The keep-alive time - the duration between two keepalive transmissions in idle condition. /// diff --git a/src/NetMQ/NetMQ.csproj b/src/NetMQ/NetMQ.csproj index 65115f1be..887626018 100644 --- a/src/NetMQ/NetMQ.csproj +++ b/src/NetMQ/NetMQ.csproj @@ -4,6 +4,8 @@ A 100% native C# port of the lightweight high performance messaging library ZeroMQ 4.0.0.0 net47;netstandard21;net8.0 + 8.0.1.0 + net47;net8.0 portable ./NetMQ.snk true diff --git a/src/NetMQ/SocketOptions.cs b/src/NetMQ/SocketOptions.cs index 38ed476d5..3fd36d986 100644 --- a/src/NetMQ/SocketOptions.cs +++ b/src/NetMQ/SocketOptions.cs @@ -283,6 +283,18 @@ public bool TcpKeepalive // See http://api.zeromq.org/3-2:zmq-getsockopt } + + /// + /// Get or set whether to use TCP keepalive retry count + /// + /// + /// + public int TcpKeepaliveCnt + { + get => m_socket.GetSocketOption(ZmqSocketOption.TcpKeepaliveCnt); + set => m_socket.SetSocketOption(ZmqSocketOption.TcpKeepaliveCnt, value); + } + /// /// Get or set the keep-alive time - the duration between two keepalive transmissions in idle condition. /// The TCP keepalive period is required by socket implementers to be configurable and by default is From 96747df96ae277675824299fe21ddd0c86f09cef Mon Sep 17 00:00:00 2001 From: Christoph Bauer Date: Thu, 17 Apr 2025 14:07:21 +0200 Subject: [PATCH 3/4] TcpKeepaliveCnt added --- src/NetMQ/Core/ZmqSocketOption.cs | 26 +++++++++++++++----------- src/NetMQ/NetMQ.csproj | 2 -- src/NetMQ/SocketOptions.cs | 5 ++++- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/NetMQ/Core/ZmqSocketOption.cs b/src/NetMQ/Core/ZmqSocketOption.cs index 97a1a446d..3a30d6925 100644 --- a/src/NetMQ/Core/ZmqSocketOption.cs +++ b/src/NetMQ/Core/ZmqSocketOption.cs @@ -200,8 +200,12 @@ internal enum ZmqSocketOption TcpKeepalive = 34, /// - /// Set TCP keep alive retry count + /// The maximum number of keepalive probes TCP should send before dropping the connection. /// + /// + /// This setting controls how many unacknowledged probes are sent before the connection is considered dead. + /// A value of -1 (the default) means to use the OS default setting. + /// TcpKeepaliveCnt = 35, /// @@ -285,7 +289,7 @@ internal enum ZmqSocketOption /// Returns the last peer routing id connect to the PEER socket /// LastPeerRoutingId = 49, - + /// /// Defines whether the socket will act as server for CURVE security. /// A value of true means the socket will act as CURVE server. @@ -294,7 +298,7 @@ internal enum ZmqSocketOption /// When you set this you must also set the server's secret key. A server socket does not need to know its own public key. /// CurveServer = 50, - + /// /// Sets the socket's long term public key. You must set this on CURVE client sockets. /// You can provide the key as 32 binary bytes, @@ -302,7 +306,7 @@ internal enum ZmqSocketOption /// To generate a public/secret key pair, NetMQKeyPair.Create. /// CurvePublicKey = 51, - + /// /// Sets the socket's long term secret key. /// You must set this on both CURVE client and server sockets. @@ -310,7 +314,7 @@ internal enum ZmqSocketOption /// To generate a public/secret key pair, NetMQKeyPair.Create. /// CurveSecretKey = 52, - + /// /// Sets the socket's long term server key. /// You must set this on CURVE client sockets. @@ -319,34 +323,34 @@ internal enum ZmqSocketOption /// To generate a public/secret key pair, use NetMQKeyPair.Create. /// CurveServerKey = 53, - + /// /// Time in milliseconds between sending heartbeat PING messages. /// HeartbeatInterval = 54, - + /// /// If remote peer receives a PING message and doesn't receive another /// message within the ttl value, it should close the connection /// (measured in tenths of a second) /// HeartbeatTtl = 55, - + /// /// Time in milliseconds to wait for a PING response before disconnecting /// HeartbeatTimeout = 56, - + /// /// Hello Message to send to peer upon connecting /// HelloMessage = 57, - + /// /// Specifies the byte-order: big-endian, vs little-endian. /// Endian = 1000, - + /// /// Specifies the max datagram size for PGM. /// diff --git a/src/NetMQ/NetMQ.csproj b/src/NetMQ/NetMQ.csproj index 887626018..65115f1be 100644 --- a/src/NetMQ/NetMQ.csproj +++ b/src/NetMQ/NetMQ.csproj @@ -4,8 +4,6 @@ A 100% native C# port of the lightweight high performance messaging library ZeroMQ 4.0.0.0 net47;netstandard21;net8.0 - 8.0.1.0 - net47;net8.0 portable ./NetMQ.snk true diff --git a/src/NetMQ/SocketOptions.cs b/src/NetMQ/SocketOptions.cs index 3fd36d986..1e6726878 100644 --- a/src/NetMQ/SocketOptions.cs +++ b/src/NetMQ/SocketOptions.cs @@ -285,9 +285,12 @@ public bool TcpKeepalive /// - /// Get or set whether to use TCP keepalive retry count + /// Get or set the maximum number of TCP keepalive probes to send before dropping the connection. /// /// + /// This value determines how many unacknowledged keepalive probes TCP should send before assuming the connection is dead. + /// A lower value means faster detection of dead peers, while a higher value allows more tolerance for temporary disruptions. + /// A value of -1 (the default) means to use the OS default setting. /// public int TcpKeepaliveCnt { From c021b9a0dd1b0d92bd7df67691136b337fec88ed Mon Sep 17 00:00:00 2001 From: Christoph Bauer Date: Thu, 24 Apr 2025 11:47:41 +0200 Subject: [PATCH 4/4] simplified some #if macros --- src/NetMQ.Tests/ClientServer.cs | 2 +- src/NetMQ/Annotations.cs | 2 +- src/NetMQ/AsyncReceiveExtensions.cs | 2 +- src/NetMQ/Core/Mechanisms/CurveClientMechanism.cs | 2 +- src/NetMQ/Core/Mechanisms/CurveServerMechanism.cs | 4 ++-- src/NetMQ/Core/Transports/Pgm/PgmSocket.cs | 2 +- src/NetMQ/Core/Transports/Tcp/TcpListener.cs | 4 ++-- src/NetMQ/Core/Utils/OpCode.cs | 2 +- src/NetMQ/Core/Utils/SpanUtility.cs | 2 +- src/NetMQ/GroupSocketExtensions.cs | 4 ++-- src/NetMQ/NetMQRuntime.cs | 2 +- src/NetMQ/NetMQSocket.cs | 6 +++--- src/NetMQ/ReceiveThreadSafeSocketExtensions.cs | 4 ++-- src/NetMQ/RoutingIdSocketExtensions.cs | 4 ++-- src/NetMQ/ThreadSafeSocket.cs | 2 +- src/NetMQ/Utils/EncodingExtensions.cs | 2 +- 16 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/NetMQ.Tests/ClientServer.cs b/src/NetMQ.Tests/ClientServer.cs index a6e1ee0d5..6f5bd89c5 100644 --- a/src/NetMQ.Tests/ClientServer.cs +++ b/src/NetMQ.Tests/ClientServer.cs @@ -82,7 +82,7 @@ public async void AsyncWithCancellationToken() await Assert.ThrowsAnyAsync(async () => await server.ReceiveStringAsync(source.Token)); } -#if NET8_0_OR_GREATER +#if NETSTANDARD2_1_OR_GREATER [Fact(Timeout = 120)] public async void AsyncEnumerableCanceled() diff --git a/src/NetMQ/Annotations.cs b/src/NetMQ/Annotations.cs index be677e68b..45e461d74 100644 --- a/src/NetMQ/Annotations.cs +++ b/src/NetMQ/Annotations.cs @@ -1,6 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE.md file in the project root for more information. -#if !NETSTANDARD2_1 && !NET8_0_OR_GREATER +#if !NET namespace System.Diagnostics.CodeAnalysis { diff --git a/src/NetMQ/AsyncReceiveExtensions.cs b/src/NetMQ/AsyncReceiveExtensions.cs index f7ddfe276..9969a1366 100644 --- a/src/NetMQ/AsyncReceiveExtensions.cs +++ b/src/NetMQ/AsyncReceiveExtensions.cs @@ -1,4 +1,4 @@ -#if NET8_0_OR_GREATER || NET8_0_OR_GREATER || NETSTANDARD2_0 || NETSTANDARD2_1 || NET47 +#if NET || NET47 using System; using System.Collections.Generic; diff --git a/src/NetMQ/Core/Mechanisms/CurveClientMechanism.cs b/src/NetMQ/Core/Mechanisms/CurveClientMechanism.cs index 75a677a6b..01b0c8d7d 100644 --- a/src/NetMQ/Core/Mechanisms/CurveClientMechanism.cs +++ b/src/NetMQ/Core/Mechanisms/CurveClientMechanism.cs @@ -189,7 +189,7 @@ PullMsgResult ProduceInitiate(ref Msg msg) VouchNoncePrefix.CopyTo(vouchNonce); using var rng = RandomNumberGenerator.Create(); -#if NET8_0_OR_GREATER || NETSTANDARD2_1 +#if NET rng.GetBytes(vouchNonce.Slice(8)); #else byte[] temp = new byte[16]; diff --git a/src/NetMQ/Core/Mechanisms/CurveServerMechanism.cs b/src/NetMQ/Core/Mechanisms/CurveServerMechanism.cs index a3747aaa2..370989e33 100644 --- a/src/NetMQ/Core/Mechanisms/CurveServerMechanism.cs +++ b/src/NetMQ/Core/Mechanisms/CurveServerMechanism.cs @@ -157,7 +157,7 @@ PullMsgResult ProduceWelcome(ref Msg msg) // 8-byte prefix plus 16-byte random nonce CookieNoncePrefix.CopyTo(cookieNonce); using var rng = RandomNumberGenerator.Create(); -#if NET8_0_OR_GREATER || NETSTANDARD2_1 +#if NET rng.GetBytes(cookieNonce.Slice(8)); #else byte[] temp = new byte[16]; @@ -184,7 +184,7 @@ PullMsgResult ProduceWelcome(ref Msg msg) // Create full nonce for encryption // 8-byte prefix plus 16-byte random nonce WelcomeNoncePrefix.CopyTo(welcomeNonce); -#if NET8_0_OR_GREATER || NETSTANDARD2_1 +#if NET rng.GetBytes(welcomeNonce.Slice(8)); #else rng.GetBytes(temp); diff --git a/src/NetMQ/Core/Transports/Pgm/PgmSocket.cs b/src/NetMQ/Core/Transports/Pgm/PgmSocket.cs index c2440cbb1..851178565 100644 --- a/src/NetMQ/Core/Transports/Pgm/PgmSocket.cs +++ b/src/NetMQ/Core/Transports/Pgm/PgmSocket.cs @@ -97,7 +97,7 @@ internal void Init() Debug.WriteLine(xMsg); // If running on Microsoft Windows, suggest to the developer that he may need to install MSMQ in order to get PGM socket support. -#if NET8_0_OR_GREATER || NETSTANDARD1_1_OR_GREATER +#if NET bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); #else bool isWindows = true; diff --git a/src/NetMQ/Core/Transports/Tcp/TcpListener.cs b/src/NetMQ/Core/Transports/Tcp/TcpListener.cs index d38c2ce3b..c4319f873 100644 --- a/src/NetMQ/Core/Transports/Tcp/TcpListener.cs +++ b/src/NetMQ/Core/Transports/Tcp/TcpListener.cs @@ -22,7 +22,7 @@ You should have received a copy of the GNU Lesser General Public License using System; using System.Diagnostics; using System.Net.Sockets; -#if NET8_0_OR_GREATER || NETSTANDARD2_0 || NETSTANDARD2_1 +#if NET using System.Runtime.InteropServices; #endif using AsyncIO; @@ -141,7 +141,7 @@ public virtual void SetAddress(string addr) } } -#if NET8_0_OR_GREATER || NETSTANDARD2_0 || NETSTANDARD2_1 +#if NET // This command is failing on linux if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) m_handle.ExclusiveAddressUse = false; diff --git a/src/NetMQ/Core/Utils/OpCode.cs b/src/NetMQ/Core/Utils/OpCode.cs index 64b9daa6f..bd1c8f6b1 100644 --- a/src/NetMQ/Core/Utils/OpCode.cs +++ b/src/NetMQ/Core/Utils/OpCode.cs @@ -20,7 +20,7 @@ public static bool Open() string val = Environment.GetEnvironmentVariable("NETQM_SUPPRESS_RDTSC"); if (!string.IsNullOrEmpty(val)) return false; -#if NET8_0_OR_GREATER || NETSTANDARD1_1_OR_GREATER || NET471_OR_GREATER +#if NET if (RuntimeInformation.ProcessArchitecture != Architecture.X86 && RuntimeInformation.ProcessArchitecture != Architecture.X64) { diff --git a/src/NetMQ/Core/Utils/SpanUtility.cs b/src/NetMQ/Core/Utils/SpanUtility.cs index 61b646f72..6b4b111f4 100644 --- a/src/NetMQ/Core/Utils/SpanUtility.cs +++ b/src/NetMQ/Core/Utils/SpanUtility.cs @@ -7,7 +7,7 @@ internal static class SpanUtility { public static string ToAscii(Span bytes) { -#if NET8_0_OR_GREATER || NETSTANDARD2_1 +#if NET return Encoding.ASCII.GetString(bytes); #else return Encoding.ASCII.GetString(bytes.ToArray()); diff --git a/src/NetMQ/GroupSocketExtensions.cs b/src/NetMQ/GroupSocketExtensions.cs index 7ce42202e..86d7764e7 100644 --- a/src/NetMQ/GroupSocketExtensions.cs +++ b/src/NetMQ/GroupSocketExtensions.cs @@ -376,7 +376,7 @@ public static bool TryReceiveBytes(this IGroupInSocket socket, TimeSpan timeout, #region AsyncEnumerable -#if NET8_0_OR_GREATER || NETSTANDARD2_1 +#if NET /// /// Provides a consuming IAsyncEnumerable for receiving messages from the socket. /// @@ -575,7 +575,7 @@ public static bool TryReceiveString(this IGroupInSocket socket, TimeSpan timeout #region AsyncEnumerable -#if NET8_0_OR_GREATER || NETSTANDARD2_1 +#if NET /// /// Provides a consuming IAsyncEnumerable for receiving messages from the socket. /// diff --git a/src/NetMQ/NetMQRuntime.cs b/src/NetMQ/NetMQRuntime.cs index 09162ce85..408a8b078 100644 --- a/src/NetMQ/NetMQRuntime.cs +++ b/src/NetMQ/NetMQRuntime.cs @@ -1,4 +1,4 @@ -#if NET8_0_OR_GREATER || NETSTANDARD2_0 || NETSTANDARD2_1 || NET47 +#if NET || NET47 using System; using System.Threading; diff --git a/src/NetMQ/NetMQSocket.cs b/src/NetMQ/NetMQSocket.cs index 238b48210..fc5ced4ea 100644 --- a/src/NetMQ/NetMQSocket.cs +++ b/src/NetMQ/NetMQSocket.cs @@ -25,7 +25,7 @@ public abstract class NetMQSocket : INetMQSocket private EventHandler? m_sendReady; private int m_isClosed; - #if NET8_0_OR_GREATER || NETSTANDARD2_0 || NETSTANDARD2_1 || NET47 + #if NET || NET47 private NetMQRuntime? m_runtime; #endif @@ -249,7 +249,7 @@ public void Unbind(string address) /// Closes this socket, rendering it unusable. Equivalent to calling . public void Close() { - #if NET8_0_OR_GREATER || NETSTANDARD2_0 || NETSTANDARD2_1 || NET47 + #if NET || NET47 if (m_runtime != null) { m_runtime.Remove(this); @@ -391,7 +391,7 @@ public virtual bool TrySend(ref Msg msg, TimeSpan timeout, bool more) #endregion - #if NET8_0_OR_GREATER || NETSTANDARD2_0 || NETSTANDARD2_1 || NET47 + #if NET || NET47 internal void AttachToRuntime() { diff --git a/src/NetMQ/ReceiveThreadSafeSocketExtensions.cs b/src/NetMQ/ReceiveThreadSafeSocketExtensions.cs index 73380b464..832a9242d 100644 --- a/src/NetMQ/ReceiveThreadSafeSocketExtensions.cs +++ b/src/NetMQ/ReceiveThreadSafeSocketExtensions.cs @@ -119,7 +119,7 @@ public static ValueTask ReceiveBytesAsync(this IThreadSafeInSocket socke #region AsyncEnumerable -#if NET8_0_OR_GREATER || NETSTANDARD2_1 +#if NET /// /// Provides a consuming IAsyncEnumerable for receiving messages from the socket. @@ -302,7 +302,7 @@ public static ValueTask ReceiveStringAsync(this IThreadSafeInSocket sock #region AsyncEnumerable -#if NET8_0_OR_GREATER || NETSTANDARD2_1 +#if NET /// /// Provides a consuming IAsyncEnumerable for receiving messages from the socket. diff --git a/src/NetMQ/RoutingIdSocketExtensions.cs b/src/NetMQ/RoutingIdSocketExtensions.cs index e2e260ecb..7fd2acc48 100644 --- a/src/NetMQ/RoutingIdSocketExtensions.cs +++ b/src/NetMQ/RoutingIdSocketExtensions.cs @@ -372,7 +372,7 @@ public static bool TryReceiveBytes(this IRoutingIdSocket socket, TimeSpan timeou #region AsyncEnumerable -#if NET8_0_OR_GREATER || NETSTANDARD2_1 +#if NET /// /// Provides a consuming IAsyncEnumerable for receiving messages from the socket. @@ -564,7 +564,7 @@ public static bool TryReceiveString(this IRoutingIdSocket socket, TimeSpan timeo #region AsyncEnumerable -#if NET8_0_OR_GREATER || NETSTANDARD2_1 +#if NET /// /// Provides a consuming IAsyncEnumerable for receiving messages from the socket. diff --git a/src/NetMQ/ThreadSafeSocket.cs b/src/NetMQ/ThreadSafeSocket.cs index 14611ff18..f0c8a2325 100644 --- a/src/NetMQ/ThreadSafeSocket.cs +++ b/src/NetMQ/ThreadSafeSocket.cs @@ -200,7 +200,7 @@ public void Unbind(string address) /// Closes this socket, rendering it unusable. Equivalent to calling . public void Close() { - // #if NET8_0_OR_GREATER || NETSTANDARD2_0 || NETSTANDARD2_1 || NET47 + // #if NET || NET47 // if (m_runtime != null) // { // m_runtime.Remove(this); diff --git a/src/NetMQ/Utils/EncodingExtensions.cs b/src/NetMQ/Utils/EncodingExtensions.cs index c5e821276..2a297f25b 100644 --- a/src/NetMQ/Utils/EncodingExtensions.cs +++ b/src/NetMQ/Utils/EncodingExtensions.cs @@ -1,4 +1,4 @@ -#if !NETSTANDARD2_1 && !NET8_0_OR_GREATER +#if !NET using System; using System.Text;