diff --git a/VL.CoreLib/src/IO/Socket/UdpSocketClient.cs b/VL.CoreLib/src/IO/Socket/UdpSocketClient.cs
new file mode 100644
index 00000000..231c3236
--- /dev/null
+++ b/VL.CoreLib/src/IO/Socket/UdpSocketClient.cs
@@ -0,0 +1,58 @@
+using System.Net;
+using System.Net.Sockets;
+using VL.Core.Import;
+using VL.Lib.Basics.Resources;
+using VL.Lib.IO.Socket;
+using NetSocket = System.Net.Sockets.Socket;
+using NetUtils = VL.Lib.IO.Net.NetUtils;
+
+[assembly: ImportType(typeof(UdpSocket), Category = "IO.Socket.Advanced")]
+
+namespace VL.Lib.IO.Socket
+{
+ ///
+ /// Manages a UDP socket client provider.
+ ///
+ [ProcessNode]
+ public class UdpSocketClient
+ {
+ ResourceProviderMonitor FCurrentProvider;
+ private bool FConnect = false;
+ private IPEndPoint FRemoteIPEndPoint;
+
+ ///
+ /// Configures the internally managed socket provider.
+ ///
+ /// The remote end point to use.
+ /// Whether or not to connect the socket.
+ /// Whether or not the socket is active.
+ /// A socket provider which can be used by multiple threads in parallel.
+ public IResourceProvider Update(IPEndPoint remoteEndpoint, bool connect, bool enabled = true)
+ {
+ if (!NetUtils.Equals(FRemoteIPEndPoint, remoteEndpoint) || FConnect != connect)
+ {
+ FConnect = connect;
+ FRemoteIPEndPoint = remoteEndpoint;
+
+ FCurrentProvider = ResourceProvider.New(() =>
+ {
+ var socket = new NetSocket(SocketType.Dgram, ProtocolType.Udp);
+ socket.ExclusiveAddressUse = false;
+ socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
+ if (connect && remoteEndpoint != null)
+ socket.Connect(remoteEndpoint);
+ return socket;
+ }).ShareInParallel().Monitor();
+ }
+
+ if (enabled)
+ return FCurrentProvider;
+ return null;
+ }
+
+ ///
+ /// Whether or not the socket is open.
+ ///
+ public bool IsOpen => FCurrentProvider?.SinkCount > 0;
+ }
+}