├── .gitignore ├── .travis.yml ├── AssemblyInfo.cs ├── Devices ├── PubSubDevice.cs ├── PushPullDevice.cs ├── RouterDealerDevice.cs └── StreamDealerDevice.cs ├── LICENSE.txt ├── Monitoring ├── ZMonitor.cs ├── ZMonitorEventArgs.cs ├── ZMonitorEventData.cs ├── ZMonitorEvents.cs ├── ZMonitorFileDescriptorEventArgs.cs ├── ZMonitorIntervalEventArgs.cs └── ZMonitors.cs ├── Platform ├── DispoIntPtr.Ansi.cs ├── DispoIntPtr.cs ├── Platform.MacOSX.cs ├── Platform.Posix.cs ├── Platform.Win32.cs ├── Platform.__Internal.cs ├── Platform.cs ├── UnmanagedLibrary.cs ├── zmq.cs ├── zmq_pollitem_posix_t.cs └── zmq_pollitem_windows_t.cs ├── README.md ├── RouterMandatory.cs ├── TcpKeepaliveBehaviour.cs ├── Z85.cs ├── ZActor.cs ├── ZAuth.cs ├── ZCert.cs ├── ZCertStore.cs ├── ZContext.cs ├── ZContextOption.cs ├── ZDevice.cs ├── ZError.cs ├── ZException.cs ├── ZFrame.cs ├── ZFrameOption.cs ├── ZGuideExamples ├── AssemblyInfo.cs ├── Program.cs ├── ProgramRunner.cs ├── README.md ├── Z85Encode.cs ├── ZGuideExamples.mono.csproj ├── ZGuideExamples.netcore.csproj ├── ZGuideExamples.vs.csproj ├── asyncsrv.cs ├── eagain.cs ├── espresso.cs ├── flcliapi.cs ├── flclient1.cs ├── flclient2.cs ├── flclient3.cs ├── flserver1.cs ├── flserver2.cs ├── flserver3.cs ├── hwclient.cs ├── hwserver.cs ├── identity.cs ├── interrupt.cs ├── ironhouseclient.cs ├── ironhouseserver.cs ├── lbbroker.cs ├── lpclient.cs ├── lpserver.cs ├── lvcache.cs ├── mdbroker.cs ├── mdcliapi.cs ├── mdcliapi2.cs ├── mdclient.cs ├── mdclient2.cs ├── mdp.cs ├── mdworker.cs ├── mdwrkapi.cs ├── mmiecho.cs ├── msgqueue.cs ├── mspoller.cs ├── msreader.cs ├── mtrelay.cs ├── mtserver.cs ├── pathopub.cs ├── pathosub.cs ├── peering1.cs ├── peering2.cs ├── ppqueue.cs ├── ppworker.cs ├── project.json ├── psenvpub.cs ├── psenvsub.cs ├── rrbroker.cs ├── rrclient.cs ├── rrworker.cs ├── rtdealer.cs ├── rtreq.cs ├── spqueue.cs ├── spworker.cs ├── suisnail.cs ├── syncpub.cs ├── syncsub.cs ├── tasksink.cs ├── tasksink2.cs ├── taskvent.cs ├── taskwork.cs ├── taskwork2.cs ├── ticlient.cs ├── titanic.cs ├── tripping.cs ├── version.cs ├── wuclient.cs ├── wuproxy.cs └── wuserver.cs ├── ZMessage.cs ├── ZPoll.cs ├── ZPollItem.cs ├── ZPollItems.Posix.cs ├── ZPollItems.Win32.cs ├── ZPollItems.cs ├── ZSocket.cs ├── ZSocketFlags.cs ├── ZSocketOption.cs ├── ZSocketSetup.cs ├── ZSocketType.cs ├── ZSymbol.cs ├── ZThread.cs ├── ZeroMQ.7z.Release.cmd ├── ZeroMQ.gif ├── ZeroMQ.ico ├── ZeroMQ.mono.csproj ├── ZeroMQ.netcore.csproj ├── ZeroMQ.nuspec ├── ZeroMQ.snk ├── ZeroMQ.targets ├── ZeroMQ.vs.csproj ├── ZeroMQ.zip.Release.sh ├── app.config ├── appveyor.yml ├── build.sh ├── clrzmq4.mono.sln ├── clrzmq4.netcore.sln ├── clrzmq4.vs.sln ├── project.json └── travis.preinstall.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | **/.* 3 | bin/* 4 | obj/* 5 | **/bin/* 6 | **/obj/* 7 | 8 | packages/* 9 | 10 | *.lock* 11 | *.cache* 12 | *.old* 13 | *.user* 14 | *.userprefs 15 | *.suo 16 | *.nupkg 17 | 18 | amd64/* 19 | i386/* 20 | 21 | ZeroMQ.*.zip 22 | 23 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | solution: clrzmq4.mono.sln 2 | language: csharp 3 | mono: latest 4 | #sudo: required 5 | 6 | matrix: 7 | include: 8 | - os: linux 9 | dist: xenial 10 | 11 | - os: osx 12 | osx_image: xcode9.4 13 | # osx_image: xcode7.3 14 | 15 | before_install: 16 | - chmod a+x ./travis.preinstall.sh 17 | - chmod a+x ./build.sh 18 | 19 | install: 20 | - ./travis.preinstall.sh 21 | - ./build.sh 22 | 23 | #before_script: 24 | 25 | script: 26 | - mono bin/Release/ZGuideExamples.exe Version 27 | - mono bin/Release/ZGuideExamples.exe EAgain 28 | - mono bin/Release/ZGuideExamples.exe Espresso 29 | - mono bin/Release/ZGuideExamples.exe AsyncSrv 30 | -------------------------------------------------------------------------------- /AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle("ZeroMQ")] 8 | [assembly: AssemblyDescription("ZeroMQ CLR namespace")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("ØMQ")] 11 | [assembly: AssemblyProduct("ØMQ")] 12 | [assembly: AssemblyCopyright("ØMQ")] 13 | [assembly: AssemblyTrademark("")] 14 | // [assembly: AssemblyCulture("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion("4.1.0.31")] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | // [assembly: AssemblyDelaySign(false)] 26 | // [assembly: AssemblyKeyFile("ZeroMQ.snk")] 27 | 28 | -------------------------------------------------------------------------------- /Devices/PubSubDevice.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ.Devices 2 | { 3 | using System; 4 | 5 | /// 6 | /// Device for a Publisher and Subscribers 7 | /// 8 | public class PubSubDevice : ZDevice 9 | { 10 | /// 11 | /// The frontend for a forwarder device. 12 | /// 13 | public static readonly ZSocketType FrontendType = ZSocketType.XSUB; 14 | 15 | /// 16 | /// The backend for a forwarder device. 17 | /// 18 | public static readonly ZSocketType BackendType = ZSocketType.XPUB; 19 | 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | public PubSubDevice() : this(ZContext.Current) { } 24 | 25 | /// 26 | /// Initializes a new instance of the class. 27 | /// 28 | public PubSubDevice(ZContext context) 29 | : base(context, FrontendType, BackendType) 30 | { 31 | BackendSetup.SubscribeAll(); 32 | } 33 | 34 | /// 35 | /// Initializes a new instance of the class. 36 | /// 37 | public PubSubDevice(string frontendBindAddr, string backendBindAddr) 38 | : this(ZContext.Current, frontendBindAddr, backendBindAddr) 39 | { } 40 | 41 | /// 42 | /// Initializes a new instance of the class. 43 | /// 44 | public PubSubDevice(ZContext context, string frontendBindAddr, string backendBindAddr) 45 | : base(context, FrontendType, BackendType) 46 | { 47 | FrontendSetup.Bind(frontendBindAddr); 48 | BackendSetup.Bind(backendBindAddr); 49 | BackendSetup.SubscribeAll(); 50 | } 51 | 52 | /// 53 | /// Forwards requests from the frontend socket to the backend socket. 54 | /// 55 | protected override bool FrontendHandler(ZSocket socket, out ZMessage message, out ZError error) 56 | { 57 | return FrontendSocket.Forward(BackendSocket, out message, out error); 58 | } 59 | 60 | /// 61 | /// PubSub Forwards the Subscription messages 62 | /// 63 | protected override bool BackendHandler(ZSocket args, out ZMessage message, out ZError error) 64 | { 65 | return BackendSocket.Forward(FrontendSocket, out message, out error); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /Devices/PushPullDevice.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ.Devices 2 | { 3 | using System; 4 | 5 | /// 6 | /// Queuing Push-Pull Device 7 | /// 8 | public class PushPullDevice : ZDevice 9 | { 10 | /// 11 | /// The frontend for a streamer device. 12 | /// 13 | public static readonly ZSocketType FrontendType = ZSocketType.PULL; 14 | 15 | /// 16 | /// The backend for a streamer device. 17 | /// 18 | public static readonly ZSocketType BackendType = ZSocketType.PUSH; 19 | 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | public PushPullDevice() : this(ZContext.Current) { } 24 | 25 | /// 26 | /// Initializes a new instance of the class. 27 | /// 28 | public PushPullDevice(ZContext context) 29 | : base(context, FrontendType, BackendType) 30 | { } 31 | 32 | /// 33 | /// Initializes a new instance of the class. 34 | /// 35 | public PushPullDevice(string frontendBindAddr, string backendBindAddr) 36 | : this(ZContext.Current, frontendBindAddr, backendBindAddr) 37 | { } 38 | 39 | /// 40 | /// Initializes a new instance of the class. 41 | /// 42 | public PushPullDevice(ZContext context, string frontendBindAddr, string backendBindAddr) 43 | : base(context, FrontendType, BackendType) 44 | { 45 | FrontendSetup.Bind(frontendBindAddr); 46 | BackendSetup.Bind(backendBindAddr); 47 | } 48 | 49 | /// 50 | /// Forwards requests from the frontend socket to the backend socket. 51 | /// 52 | protected override bool FrontendHandler(ZSocket args, out ZMessage message, out ZError error) 53 | { 54 | return FrontendSocket.Forward(BackendSocket, out message, out error); 55 | } 56 | 57 | /// 58 | /// Not implemented for the . 59 | /// 60 | protected override bool BackendHandler(ZSocket args, out ZMessage message, out ZError error) 61 | { 62 | throw new NotSupportedException(); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /Devices/RouterDealerDevice.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ.Devices 2 | { 3 | /// 4 | /// A Device on Routers and Dealers 5 | /// 6 | public class RouterDealerDevice : ZDevice 7 | { 8 | /// 9 | /// The frontend for a queue device. 10 | /// 11 | public static readonly ZSocketType FrontendType = ZSocketType.ROUTER; 12 | 13 | /// 14 | /// The backend for a queue device. 15 | /// 16 | public static readonly ZSocketType BackendType = ZSocketType.DEALER; 17 | 18 | /// 19 | /// Initializes a new instance of the class. 20 | /// 21 | public RouterDealerDevice() : this(ZContext.Current) { } 22 | 23 | /// 24 | /// Initializes a new instance of the class. 25 | /// 26 | public RouterDealerDevice(ZContext context) 27 | : base(context, FrontendType, BackendType) 28 | { } 29 | 30 | /// 31 | /// Initializes a new instance of the class 32 | /// and binds to the specified Frontend and Backend address. 33 | /// 34 | public RouterDealerDevice(string frontendBindAddr, string backendBindAddr) 35 | : this(ZContext.Current, frontendBindAddr, backendBindAddr) 36 | { } 37 | 38 | /// 39 | /// Initializes a new instance of the class 40 | /// and binds to the specified Frontend and Backend address. 41 | /// 42 | public RouterDealerDevice(ZContext context, string frontendBindAddr, string backendBindAddr) 43 | : base(context, FrontendType, BackendType) 44 | { 45 | FrontendSetup.Bind(frontendBindAddr); 46 | BackendSetup.Bind(backendBindAddr); 47 | } 48 | 49 | /// 50 | /// Forwards requests from the frontend socket to the backend socket. 51 | /// 52 | protected override bool FrontendHandler(ZSocket args, out ZMessage message, out ZError error) 53 | { 54 | return FrontendSocket.Forward(BackendSocket, out message, out error); 55 | } 56 | 57 | /// 58 | /// Forwards replies from the backend socket to the frontend socket. 59 | /// 60 | protected override bool BackendHandler(ZSocket args, out ZMessage message, out ZError error) 61 | { 62 | return BackendSocket.Forward(FrontendSocket, out message, out error); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /Monitoring/ZMonitorEventArgs.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ.Monitoring 2 | { 3 | using System; 4 | 5 | /// 6 | /// A base class for the all ZmqMonitor events. 7 | /// 8 | public class ZMonitorEventArgs : EventArgs 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | /// The that triggered the event. 14 | /// The peer address. 15 | public ZMonitorEventArgs(ZMonitor monitor, ZMonitorEventData ed) 16 | { 17 | this.Monitor = monitor; 18 | this.Event = ed; 19 | } 20 | 21 | public ZMonitorEventData Event { get; private set; } 22 | 23 | /// 24 | /// Gets the monitor that triggered the event. 25 | /// 26 | public ZMonitor Monitor { get; private set; } 27 | } 28 | } -------------------------------------------------------------------------------- /Monitoring/ZMonitorEventData.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ.Monitoring 2 | { 3 | using System; 4 | 5 | public struct ZMonitorEventData 6 | { 7 | public ZMonitorEvents Event; 8 | public Int32 EventValue; 9 | public String Address; 10 | } 11 | } -------------------------------------------------------------------------------- /Monitoring/ZMonitorEvents.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ.Monitoring 2 | { 3 | using System; 4 | 5 | /// 6 | /// Socket transport events (for TCP and IPC sockets) that can be monitored. 7 | /// 8 | [Flags] 9 | public enum ZMonitorEvents 10 | { 11 | /// 12 | /// Triggered when a connection has been established to a remote peer. 13 | /// 14 | Connected = 1, 15 | 16 | /// 17 | /// Triggered when an immediate connection attempt is delayed and it's completion is being polled for. 18 | /// 19 | ConnectDelayed = 2, 20 | 21 | /// 22 | /// Triggered when a connection attempt is being handled by reconnect timer. The reconnect interval is recomputed for each attempt. 23 | /// 24 | ConnectRetried = 4, 25 | 26 | /// 27 | /// Triggered when a socket is successfully bound to a an interface. 28 | /// 29 | Listening = 8, 30 | 31 | /// 32 | /// Triggered when a socket could not bind to a given interface. 33 | /// 34 | BindFailed = 16, 35 | 36 | /// 37 | /// Triggered when a connection from a remote peer has been established with a socket's listen address. 38 | /// 39 | Accepted = 32, 40 | 41 | /// 42 | /// Triggered when a connection attempt to a socket's bound address fails. 43 | /// 44 | AcceptFailed = 64, 45 | 46 | /// 47 | /// Triggered when a connection's underlying descriptor has been closed. 48 | /// 49 | Closed = 128, 50 | 51 | /// 52 | /// Triggered when a descriptor could not be released back to the OS. 53 | /// 54 | CloseFailed = 256, 55 | 56 | /// 57 | /// Triggered when the stream engine (tcp and ipc specific) detects a corrupted / broken session. 58 | /// 59 | Disconnected = 512, 60 | 61 | /// 62 | /// Monitoring on this socket ended. 63 | /// 64 | Stopped = 1024, 65 | 66 | /// 67 | /// Any event, maybe readable from EventValue. 68 | /// 69 | AllEvents = 0xFFFF 70 | } 71 | } -------------------------------------------------------------------------------- /Monitoring/ZMonitorFileDescriptorEventArgs.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ.Monitoring 2 | { 3 | using System; 4 | using lib; 5 | 6 | /// 7 | /// Provides data for , , , and events. 8 | /// 9 | public class ZMonitorFileDescriptorEventArgs : ZMonitorEventArgs 10 | { 11 | internal ZMonitorFileDescriptorEventArgs(ZMonitor monitor, ZMonitorEventData data) 12 | : base(monitor, data) 13 | { 14 | if (Platform.Kind == PlatformKind.Posix) 15 | { 16 | this.FileDescriptor_Posix = data.EventValue; 17 | } 18 | else if (Platform.Kind == PlatformKind.Win32) 19 | { 20 | this.FileDescriptor_Windows = new IntPtr(data.EventValue); 21 | } 22 | else 23 | { 24 | throw new PlatformNotSupportedException(); 25 | } 26 | } 27 | 28 | /// 29 | /// Gets the monitor descriptor (Posix) 30 | /// 31 | public int FileDescriptor_Posix { get; private set; } 32 | 33 | /// 34 | /// Gets the monitor descriptor (Windows) 35 | /// 36 | public IntPtr FileDescriptor_Windows { get; private set; } 37 | } 38 | } -------------------------------------------------------------------------------- /Monitoring/ZMonitorIntervalEventArgs.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ.Monitoring 2 | { 3 | /// 4 | /// Provides data for event. 5 | /// 6 | public class ZMonitorIntervalEventArgs : ZMonitorEventArgs 7 | { 8 | internal ZMonitorIntervalEventArgs(ZMonitor monitor, ZMonitorEventData data) 9 | : base(monitor, data) 10 | { 11 | this.Interval = data.EventValue; 12 | } 13 | 14 | /// 15 | /// Gets the computed reconnect interval. 16 | /// 17 | public int Interval { get; private set; } 18 | } 19 | } -------------------------------------------------------------------------------- /Monitoring/ZMonitors.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | using ZeroMQ.lib; 5 | 6 | namespace ZeroMQ.Monitoring 7 | { 8 | 9 | /// 10 | /// Defines extension methods related to monitoring for instances. 11 | /// 12 | public static class ZMonitors 13 | { 14 | /// 15 | /// Spawns a socket that publishes all events for 16 | /// the specified socket over the inproc transport at the given endpoint. 17 | /// 18 | public static bool Monitor(this ZSocket socket, string endpoint) 19 | { 20 | ZError error; 21 | if (!Monitor(socket, endpoint, ZMonitorEvents.AllEvents, out error)) 22 | { 23 | throw new ZException(error); 24 | } 25 | return true; 26 | } 27 | 28 | /// 29 | /// Spawns a socket that publishes all events for 30 | /// the specified socket over the inproc transport at the given endpoint. 31 | /// 32 | public static bool Monitor(this ZSocket socket, string endpoint, out ZError error) 33 | { 34 | return Monitor(socket, endpoint, ZMonitorEvents.AllEvents, out error); 35 | } 36 | 37 | /// 38 | /// Spawns a socket that publishes all events for 39 | /// the specified socket over the inproc transport at the given endpoint. 40 | /// 41 | public static bool Monitor(this ZSocket socket, string endpoint, ZMonitorEvents eventsToMonitor) 42 | { 43 | ZError error; 44 | if (!Monitor(socket, endpoint, eventsToMonitor, out error)) 45 | { 46 | throw new ZException(error); 47 | } 48 | return true; 49 | } 50 | 51 | /// 52 | /// Spawns a socket that publishes all events for 53 | /// the specified socket over the inproc transport at the given endpoint. 54 | /// 55 | public static bool Monitor(this ZSocket socket, string endpoint, ZMonitorEvents eventsToMonitor, out ZError error) 56 | { 57 | if (socket == null) 58 | { 59 | throw new ArgumentNullException("socket"); 60 | } 61 | 62 | if (endpoint == null) 63 | { 64 | throw new ArgumentNullException("endpoint"); 65 | } 66 | 67 | if (endpoint == string.Empty) 68 | { 69 | throw new ArgumentException("Unable to publish socket events to an empty endpoint.", "endpoint"); 70 | } 71 | 72 | error = ZError.None; 73 | 74 | using (var endpointPtr = DispoIntPtr.AllocString(endpoint)) 75 | { 76 | while (-1 == zmq.socket_monitor(socket.SocketPtr, endpointPtr, (Int32)eventsToMonitor)) 77 | { 78 | error = ZError.GetLastErr(); 79 | 80 | if (error == ZError.EINTR) 81 | { 82 | error = default(ZError); 83 | continue; 84 | } 85 | 86 | return false; 87 | } 88 | } 89 | return true; 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /Platform/DispoIntPtr.Ansi.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | 3 | namespace ZeroMQ.lib 4 | { 5 | using System; 6 | using System.Text; 7 | using System.Threading; 8 | using System.Runtime.InteropServices; 9 | 10 | internal sealed partial class DispoIntPtr : IDisposable 11 | { 12 | public static class Ansi 13 | { 14 | unsafe internal static DispoIntPtr AllocStringNative(string str, out int byteCount) 15 | { 16 | // use builtin allocation 17 | var dispPtr = new DispoIntPtr(); 18 | dispPtr._ptr = Marshal.StringToHGlobalAnsi(str); 19 | dispPtr.isAllocated = true; 20 | 21 | byteCount = Encoding.Default.GetByteCount(str); 22 | return dispPtr; /**/ 23 | 24 | /* use encoding or Encoding.Default ( system codepage of ANSI ) 25 | var enc = Encoding.Default.GetEncoder(); 26 | 27 | // var encoded = new byte[length]; 28 | // Marshal.Copy(encoded, 0, dispPtr._ptr, length); 29 | 30 | IntPtr ptr; 31 | int charCount = str.Length; 32 | 33 | fixed (char* strP = str) 34 | { 35 | byteCount = enc.GetByteCount(strP, charCount, false); 36 | 37 | ptr = Marshal.AllocHGlobal(byteCount + 1); 38 | 39 | enc.GetBytes(strP, charCount, (byte*)ptr, byteCount, true); 40 | 41 | *((byte*)ptr + byteCount) = 0x00; 42 | } 43 | 44 | var dispPtr = new DispoIntPtr (); 45 | dispPtr._ptr = ptr; 46 | dispPtr.isAllocated = true; 47 | 48 | // and a C char 0x00 terminator 49 | // Marshal.WriteByte(dispPtr._ptr + length, byte.MinValue); 50 | // *((byte*)dispPtr._ptr + length) = 0x00; 51 | 52 | return dispPtr; /**/ 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /Platform/DispoIntPtr.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | 3 | namespace ZeroMQ.lib 4 | { 5 | using System; 6 | using System.Text; 7 | using System.Threading; 8 | using System.Runtime.InteropServices; 9 | 10 | internal sealed partial class DispoIntPtr : IDisposable 11 | { 12 | private delegate DispoIntPtr AllocStringNativeDelegate(string str, out int byteCount); 13 | 14 | private static readonly AllocStringNativeDelegate AllocStringNative = Ansi.AllocStringNative; 15 | 16 | /* static DispoIntPtr() { 17 | // Platform.SetupPlatformImplementation(typeof(DispoIntPtr)); 18 | } */ 19 | 20 | public static DispoIntPtr Alloc(int size) 21 | { 22 | var dispPtr = new DispoIntPtr(); 23 | dispPtr._ptr = Marshal.AllocHGlobal(size); 24 | dispPtr.isAllocated = true; 25 | return dispPtr; 26 | } 27 | 28 | public static DispoIntPtr AllocString(string str) 29 | { 30 | int byteCount; 31 | return AllocString(str, out byteCount); 32 | } 33 | 34 | public static DispoIntPtr AllocString(string str, out int byteCount) 35 | { 36 | return AllocStringNative(str, out byteCount); 37 | } 38 | 39 | public static implicit operator IntPtr(DispoIntPtr dispoIntPtr) 40 | { 41 | return dispoIntPtr == null ? IntPtr.Zero : dispoIntPtr._ptr; 42 | } 43 | 44 | unsafe public static explicit operator void*(DispoIntPtr dispoIntPtr) 45 | { 46 | return dispoIntPtr == null ? (void*)null : (void*)dispoIntPtr._ptr; 47 | } 48 | 49 | unsafe public static explicit operator byte*(DispoIntPtr dispoIntPtr) 50 | { 51 | return dispoIntPtr == null ? (byte*)null : (byte*)dispoIntPtr._ptr; 52 | } 53 | 54 | unsafe public static explicit operator sbyte*(DispoIntPtr dispoIntPtr) 55 | { 56 | return dispoIntPtr == null ? (sbyte*)null : (sbyte*)dispoIntPtr._ptr; 57 | } 58 | 59 | unsafe public static explicit operator short*(DispoIntPtr dispoIntPtr) 60 | { 61 | return dispoIntPtr == null ? (short*)null : (short*)dispoIntPtr._ptr; 62 | } 63 | 64 | unsafe public static explicit operator ushort*(DispoIntPtr dispoIntPtr) 65 | { 66 | return dispoIntPtr == null ? (ushort*)null : (ushort*)dispoIntPtr._ptr; 67 | } 68 | 69 | unsafe public static explicit operator char*(DispoIntPtr dispoIntPtr) 70 | { 71 | return dispoIntPtr == null ? (char*)null : (char*)dispoIntPtr._ptr; 72 | } 73 | 74 | unsafe public static explicit operator int*(DispoIntPtr dispoIntPtr) 75 | { 76 | return dispoIntPtr == null ? (int*)null : (int*)dispoIntPtr._ptr; 77 | } 78 | 79 | unsafe public static explicit operator uint*(DispoIntPtr dispoIntPtr) 80 | { 81 | return dispoIntPtr == null ? (uint*)null : (uint*)dispoIntPtr._ptr; 82 | } 83 | 84 | unsafe public static explicit operator long*(DispoIntPtr dispoIntPtr) 85 | { 86 | return dispoIntPtr == null ? (long*)null : (long*)dispoIntPtr._ptr; 87 | } 88 | 89 | unsafe public static explicit operator ulong*(DispoIntPtr dispoIntPtr) 90 | { 91 | return dispoIntPtr == null ? (ulong*)null : (ulong*)dispoIntPtr._ptr; 92 | } 93 | 94 | private bool isAllocated; 95 | 96 | private IntPtr _ptr; 97 | 98 | public IntPtr Ptr 99 | { 100 | get { return _ptr; } 101 | } 102 | 103 | internal DispoIntPtr() { } 104 | 105 | ~DispoIntPtr() 106 | { 107 | Dispose(false); 108 | } 109 | 110 | public void Dispose() 111 | { 112 | Dispose(true); 113 | GC.SuppressFinalize(this); 114 | } 115 | 116 | void Dispose(bool disposing) 117 | { 118 | // TODO: instance ThreadStatic && do ( o == null ? return : ( lock(o, ms), check threadId, .. ) ) 119 | IntPtr handle = _ptr; 120 | if (handle != IntPtr.Zero) 121 | { 122 | if (isAllocated) 123 | { 124 | Marshal.FreeHGlobal(handle); 125 | isAllocated = false; 126 | } 127 | _ptr = IntPtr.Zero; 128 | } 129 | } 130 | 131 | /* public void ReAlloc(long size) { 132 | _ptr = Marshal.ReAllocHGlobal(_ptr, new IntPtr(size)); 133 | } */ 134 | } 135 | } -------------------------------------------------------------------------------- /Platform/Platform.MacOSX.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ.lib 2 | { 3 | 4 | public static partial class Platform 5 | { 6 | public static class MacOSX 7 | { 8 | 9 | // public const string LibraryFileExtension = ".dylib"; 10 | 11 | public static readonly string[] LibraryPaths = new string[] { 12 | "/lib/{LibraryName}*.dylib", 13 | "/lib/{LibraryName}*.dylib.*", 14 | "/usr/lib/{LibraryName}*.dylib", 15 | "/usr/lib/{LibraryName}*.dylib.*", 16 | "/usr/local/lib/{LibraryName}*.dylib", 17 | "/usr/local/lib/{LibraryName}*.dylib.*", 18 | "{DllPath}/{LibraryName}*.dylib", 19 | "{DllPath}/{LibraryName}*.dylib.*", 20 | "{Path}/{LibraryName}*.dylib", 21 | "{Path}/{LibraryName}*.dylib.*", 22 | "{AppBase}/{Arch}/{LibraryName}*.dylib", 23 | "{AppBase}/{Arch}/{LibraryName}*.dylib.*", 24 | }; 25 | 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Platform/Platform.__Internal.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | /* Example: sqlite3.cs 5 | 6 | using System; 7 | using System.Runtime.InteropServices; 8 | 9 | namespace lib 10 | { 11 | public static unsafe class sqlite3 12 | { 13 | private const string __Internal = "__Internal"; 14 | 15 | private const CallingConvention CCCdecl = CallingConvention.Cdecl; 16 | 17 | // Use a const for the library name 18 | private const string LibraryName = "sqlite3"; 19 | 20 | // Hold a handle to the static instance 21 | private static readonly UnmanagedLibrary NativeLib; 22 | 23 | // The static constructor prepares static readonly fields 24 | static sqlite3() 25 | { 26 | // (0) Initialize Library handle 27 | NativeLib = Platform.LoadUnmanagedLibrary(LibraryName); 28 | 29 | // (1) Initialize Platform information 30 | Platform.SetupImplementation(typeof(sqlite3)); 31 | 32 | // Set once LibVersion to libversion() 33 | LibVersion = Marshal.PtrToStringAnsi(libversion()); 34 | } 35 | 36 | // (2) Declare privately the extern entry point 37 | [DllImport(LibraryName, EntryPoint = "sqlite3_libversion", CallingConvention = CCCdecl)] 38 | private static extern IntPtr sqlite3_libversion(); 39 | [DllImport(__Internal, EntryPoint = "sqlite3_libversion", CallingConvention = CCCdecl)] 40 | private static extern IntPtr sqlite3_libversion__Internal(); 41 | 42 | // (3) Describe the extern function using a delegate 43 | public delegate IntPtr sqlite3_libversion_delegate (); 44 | 45 | // (4) Save and return the managed delegate to the unmanaged function 46 | // This static readonly field definition allows to be 47 | // initialized and possibly redirected by the static constructor. 48 | // 49 | // By default this is set to the extern function declaration, 50 | // it may be set to the __Internal extern function declaration. 51 | public static readonly sqlite3_libversion_delegate libversion = sqlite3_libversion; 52 | 53 | // Static LibVersion 54 | public static readonly Version LibVersion; 55 | 56 | } 57 | } 58 | 59 | */ 60 | 61 | namespace ZeroMQ.lib 62 | { 63 | public static partial class Platform 64 | { 65 | public static class __Internal 66 | { 67 | public static UnmanagedLibrary LoadUnmanagedLibrary(string libraryName) 68 | { 69 | return null; 70 | } 71 | 72 | public static SafeLibraryHandle OpenHandle(string fileName) 73 | { 74 | throw new NotSupportedException(); 75 | } 76 | 77 | public static IntPtr LoadProcedure(SafeLibraryHandle libHandle, string functionName) 78 | { 79 | throw new NotSupportedException(); 80 | } 81 | 82 | public static bool ReleaseHandle(IntPtr handle) 83 | { 84 | throw new NotSupportedException(); 85 | } 86 | 87 | public static Exception GetLastLibraryError() 88 | { 89 | return new NotSupportedException(); 90 | } 91 | } 92 | } 93 | } -------------------------------------------------------------------------------- /Platform/UnmanagedLibrary.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ.lib 2 | { 3 | using System; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using System.Reflection; 7 | using System.Runtime.InteropServices; 8 | using System.Security.Permissions; 9 | 10 | /// 11 | /// Safe handle for unmanaged libraries. See http://msdn.microsoft.com/msdnmag/issues/05/10/Reliability/ for more about safe handles. 12 | /// 13 | [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)] 14 | public sealed class SafeLibraryHandle 15 | : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid 16 | { 17 | private SafeLibraryHandle() 18 | : base(true) 19 | { } 20 | 21 | protected override bool ReleaseHandle() 22 | { 23 | return Platform.ReleaseHandle(handle); 24 | } 25 | } 26 | 27 | internal static class SafeLibraryHandles 28 | { 29 | public static bool IsNullOrInvalid(this SafeLibraryHandle handle) 30 | { 31 | return handle == null || handle.IsInvalid; 32 | } 33 | } 34 | 35 | /// 36 | /// Utility class to wrap an unmanaged shared lib and be responsible for freeing it. 37 | /// 38 | /// 39 | /// This is a managed wrapper over the native LoadLibrary, GetProcAddress, and FreeLibrary calls on Windows 40 | /// and dlopen, dlsym, and dlclose on Posix environments. 41 | /// 42 | public sealed class UnmanagedLibrary : IDisposable 43 | { 44 | private readonly string TraceLabel; 45 | 46 | private readonly SafeLibraryHandle _handle; 47 | 48 | internal UnmanagedLibrary(string libraryName, SafeLibraryHandle libraryHandle) 49 | { 50 | if (string.IsNullOrWhiteSpace(libraryName)) 51 | { 52 | throw new ArgumentException("A valid library name is expected.", "libraryName"); 53 | } 54 | if (libraryHandle.IsNullOrInvalid()) 55 | { 56 | throw new ArgumentNullException("libraryHandle"); 57 | } 58 | 59 | TraceLabel = string.Format("UnmanagedLibrary[{0}]", libraryName); 60 | 61 | _handle = libraryHandle; 62 | } 63 | 64 | /// 65 | /// Dynamically look up a function in the dll via kernel32!GetProcAddress or libdl!dlsym. 66 | /// 67 | /// Delegate type to load 68 | /// Raw name of the function in the export table. 69 | /// A delegate to the unmanaged function. 70 | /// Thrown if the given function name is not found in the library. 71 | /// 72 | /// GetProcAddress results are valid as long as the dll is not yet unloaded. This 73 | /// is very very dangerous to use since you need to ensure that the dll is not unloaded 74 | /// until after you're done with any objects implemented by the dll. For example, if you 75 | /// get a delegate that then gets an IUnknown implemented by this dll, 76 | /// you can not dispose this library until that IUnknown is collected. Else, you may free 77 | /// the library and then the CLR may call release on that IUnknown and it will crash. 78 | /// 79 | public TDelegate GetUnmanagedFunction(string functionName) where TDelegate : class 80 | { 81 | IntPtr p = Platform.LoadProcedure(_handle, functionName); 82 | 83 | if (p == IntPtr.Zero) 84 | { 85 | throw new MissingMethodException("Unable to find function '" + functionName + "' in dynamically loaded library."); 86 | } 87 | 88 | // Ideally, we'd just make the constraint on TDelegate be 89 | // System.Delegate, but compiler error CS0702 (constrained can't be System.Delegate) 90 | // prevents that. So we make the constraint system.object and do the cast from object-->TDelegate. 91 | return (TDelegate)(object)Marshal.GetDelegateForFunctionPointer(p, typeof(TDelegate)); 92 | } 93 | 94 | public void Dispose() 95 | { 96 | if (_handle != null && !_handle.IsClosed) 97 | { 98 | _handle.Close(); 99 | } 100 | } 101 | 102 | } 103 | } -------------------------------------------------------------------------------- /Platform/zmq_pollitem_posix_t.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ.lib 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | 6 | [StructLayout(LayoutKind.Sequential)] 7 | public struct zmq_pollitem_posix_t // : zmq_pollitem_i 8 | { 9 | private IntPtr socketPtr; 10 | private int fileDescriptor; // POSIX fd is an Int32 11 | private short events; 12 | private short readyEvents; 13 | 14 | public zmq_pollitem_posix_t(IntPtr socket, ZPoll pollEvents) 15 | { 16 | if (socket == IntPtr.Zero) 17 | { 18 | throw new ArgumentException("Expected a valid socket handle.", "socket"); 19 | } 20 | 21 | socketPtr = socket; 22 | fileDescriptor = 0; 23 | events = (short)pollEvents; 24 | readyEvents = (short)ZPoll.None; 25 | } 26 | 27 | public IntPtr SocketPtr 28 | { 29 | get { return socketPtr; } 30 | set { socketPtr = value; } 31 | } 32 | 33 | public int FileDescriptor 34 | { 35 | get { return fileDescriptor; } 36 | set { fileDescriptor = value; } 37 | } 38 | 39 | public short Events 40 | { 41 | get { return events; } 42 | set { events = value; } 43 | } 44 | 45 | public short ReadyEvents 46 | { 47 | get { return readyEvents; } 48 | set { readyEvents = value; } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Platform/zmq_pollitem_windows_t.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ.lib 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | 6 | [StructLayout(LayoutKind.Sequential)] 7 | public struct zmq_pollitem_windows_t // : zmq_pollitem_i 8 | { 9 | private IntPtr socketPtr; 10 | private IntPtr fileDescriptor; // Windows is an size_t 11 | private short events; 12 | private short readyEvents; 13 | 14 | public zmq_pollitem_windows_t(IntPtr socket, ZPoll pollEvents) 15 | { 16 | if (socket == IntPtr.Zero) 17 | { 18 | throw new ArgumentException("Expected a valid socket handle.", "socket"); 19 | } 20 | 21 | socketPtr = socket; 22 | fileDescriptor = IntPtr.Zero; 23 | events = (short)pollEvents; 24 | readyEvents = 0; 25 | } 26 | 27 | public IntPtr SocketPtr 28 | { 29 | get { return socketPtr; } 30 | set { socketPtr = value; } 31 | } 32 | 33 | public IntPtr FileDescriptor 34 | { 35 | get { return fileDescriptor; } 36 | set { fileDescriptor = value; } 37 | } 38 | 39 | public short Events 40 | { 41 | get { return events; } 42 | set { events = value; } 43 | } 44 | 45 | public short ReadyEvents 46 | { 47 | get { return readyEvents; } 48 | set { readyEvents = value; } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /RouterMandatory.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ 2 | { 3 | /// 4 | /// Specifies socket behavior when 5 | /// an unroutable message is encountered. 6 | /// 7 | public enum RouterMandatory 8 | { 9 | /// 10 | /// Silently discard messages. 11 | /// 12 | Discard = 0, 13 | 14 | /// 15 | /// Force sending to fail with an 'EAGAIN' error code, effectively 16 | /// enabling blocking sends. 17 | /// 18 | Report = 1, 19 | } 20 | } -------------------------------------------------------------------------------- /TcpKeepaliveBehaviour.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ 2 | { 3 | /// 4 | /// Keep-alive packets behavior for a connection. 5 | /// 6 | public enum TcpKeepaliveBehaviour : int 7 | { 8 | /// 9 | /// Use Operating System default behavior. 10 | /// 11 | Default = -1, 12 | 13 | /// 14 | /// Disable keep-alive packets. 15 | /// 16 | Disable = 0, 17 | 18 | /// 19 | /// Enable keep-alive packets. 20 | /// 21 | Enable = 1, 22 | } 23 | } -------------------------------------------------------------------------------- /Z85.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Text; 4 | using ZeroMQ.lib; 5 | 6 | namespace ZeroMQ 7 | { 8 | public static class Z85 9 | { 10 | public static void CurveKeypair(out byte[] publicKey, out byte[] secretKey) 11 | { 12 | const int destLen = 40; 13 | using (var publicKeyData = DispoIntPtr.Alloc(destLen + 1)) 14 | using (var secretKeyData = DispoIntPtr.Alloc(destLen + 1)) 15 | { 16 | if (0 != zmq.curve_keypair(publicKeyData, secretKeyData)) 17 | { 18 | throw new InvalidOperationException(); 19 | } 20 | 21 | publicKey = new byte[destLen]; 22 | Marshal.Copy(publicKeyData, publicKey, 0, destLen); 23 | 24 | secretKey = new byte[destLen]; 25 | Marshal.Copy(secretKeyData, secretKey, 0, destLen); 26 | } 27 | } 28 | 29 | public static byte[] Encode(byte[] decoded) 30 | { 31 | int dataLen = decoded.Length; 32 | if (dataLen % 4 > 0) 33 | { 34 | throw new InvalidOperationException("decoded.Length must be divisible by 4"); 35 | } 36 | int destLen = (Int32)(decoded.Length * 1.25); 37 | 38 | var data = GCHandle.Alloc(decoded, GCHandleType.Pinned); 39 | 40 | // the buffer dest must be one byte larger than destLen to accomodate the null termination character 41 | using (var dest = DispoIntPtr.Alloc(destLen + 1)) 42 | { 43 | zmq.z85_encode(dest, data.AddrOfPinnedObject(), dataLen); 44 | data.Free(); 45 | 46 | var bytes = new byte[destLen]; 47 | Marshal.Copy(dest, bytes, 0, destLen); 48 | return bytes; 49 | } 50 | } 51 | 52 | public static byte[] ToZ85Encoded(this byte[] decoded) 53 | { 54 | return Encode(decoded); 55 | } 56 | 57 | public static string ToZ85Encoded(this string decoded) 58 | { 59 | return Encode(decoded, ZContext.Encoding); 60 | } 61 | 62 | public static string ToZ85Encoded(this string decoded, Encoding encoding) 63 | { 64 | return Encode(decoded, encoding); 65 | } 66 | 67 | public static byte[] ToZ85EncodedBytes(this string decoded) 68 | { 69 | return EncodeBytes(decoded, ZContext.Encoding); 70 | } 71 | 72 | public static byte[] ToZ85EncodedBytes(this string decoded, Encoding encoding) 73 | { 74 | return EncodeBytes(decoded, encoding); 75 | } 76 | 77 | public static string Encode(string strg) 78 | { 79 | return Encode(strg, ZContext.Encoding); 80 | } 81 | 82 | public static string Encode(string strg, Encoding encoding) 83 | { 84 | byte[] encoded = EncodeBytes(strg, encoding); 85 | return encoding.GetString(encoded); 86 | } 87 | 88 | public static byte[] EncodeBytes(string strg) 89 | { 90 | return EncodeBytes(strg, ZContext.Encoding); 91 | } 92 | 93 | public static byte[] EncodeBytes(string strg, Encoding encoding) 94 | { 95 | byte[] bytes = encoding.GetBytes(strg); 96 | return Encode(bytes); 97 | } 98 | 99 | 100 | public static byte[] Decode(byte[] encoded) 101 | { 102 | int dataLen = encoded.Length; 103 | if (dataLen % 5 > 0) 104 | { 105 | throw new InvalidOperationException("encoded.Length must be divisible by 5"); 106 | } 107 | int destLen = (Int32)(encoded.Length * .8); 108 | 109 | var data = GCHandle.Alloc(encoded, GCHandleType.Pinned); 110 | 111 | using (var dest = DispoIntPtr.Alloc(destLen)) 112 | { 113 | zmq.z85_decode(dest, data.AddrOfPinnedObject()); 114 | data.Free(); 115 | 116 | var decoded = new byte[destLen]; 117 | 118 | Marshal.Copy(dest, decoded, 0, decoded.Length); 119 | 120 | return decoded; 121 | } 122 | } 123 | 124 | public static byte[] ToZ85Decoded(this byte[] encoded) 125 | { 126 | return Decode(encoded); 127 | } 128 | 129 | public static string ToZ85Decoded(this string encoded) 130 | { 131 | return Decode(encoded, ZContext.Encoding); 132 | } 133 | 134 | public static string ToZ85Decoded(this string encoded, Encoding encoding) 135 | { 136 | return Decode(encoded, encoding); 137 | } 138 | 139 | public static byte[] ToZ85DecodedBytes(this string encoded) 140 | { 141 | return DecodeBytes(encoded, ZContext.Encoding); 142 | } 143 | 144 | public static byte[] ToZ85DecodedBytes(this string encoded, Encoding encoding) 145 | { 146 | return DecodeBytes(encoded, encoding); 147 | } 148 | 149 | public static string Decode(string strg) 150 | { 151 | return Decode(strg, ZContext.Encoding); 152 | } 153 | 154 | public static string Decode(string strg, Encoding encoding) 155 | { 156 | byte[] encoded = DecodeBytes(strg, encoding); 157 | return encoding.GetString(encoded); 158 | } 159 | 160 | public static byte[] DecodeBytes(string strg, Encoding encoding) 161 | { 162 | byte[] bytes = encoding.GetBytes(strg); 163 | return Decode(bytes); 164 | } 165 | } 166 | } 167 | 168 | -------------------------------------------------------------------------------- /ZActor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ZeroMQ 4 | { 5 | public delegate void ZAction0(ZSocket backend, System.Threading.CancellationTokenSource cancellor, object[] args); 6 | 7 | public delegate void ZAction(ZContext context, ZSocket backend, System.Threading.CancellationTokenSource cancellor, object[] args); 8 | 9 | public class ZActor : ZThread 10 | { 11 | public ZContext Context { get; protected set; } 12 | 13 | public string Endpoint { get; protected set; } 14 | 15 | public ZAction Action { get; protected set; } 16 | 17 | public ZAction0 Action0 { get; protected set; } 18 | 19 | public object[] Arguments { get; protected set; } 20 | 21 | public ZSocket Backend { get; protected set; } 22 | 23 | public ZSocket Frontend { get; protected set; } 24 | 25 | public ZActor(ZContext context, ZAction action, params object[] args) 26 | : this(context, default(string), action, args) 27 | { 28 | var rnd0 = new byte[8]; 29 | using (var rng = new System.Security.Cryptography.RNGCryptoServiceProvider()) rng.GetNonZeroBytes(rnd0); 30 | this.Endpoint = string.Format("inproc://{0}", ZContext.Encoding.GetString(rnd0)); 31 | } 32 | 33 | public ZActor(ZContext context, string endpoint, ZAction action, params object[] args) 34 | : base() 35 | { 36 | this.Context = context; 37 | 38 | this.Endpoint = endpoint; 39 | this.Action = action; 40 | this.Arguments = args; 41 | } 42 | 43 | /// 44 | /// You are using ZContext.Current! 45 | /// 46 | public ZActor(ZAction0 action, params object[] args) 47 | : this(default(string), action, args) 48 | { 49 | var rnd0 = new byte[8]; 50 | using (var rng = new System.Security.Cryptography.RNGCryptoServiceProvider()) rng.GetNonZeroBytes(rnd0); 51 | this.Endpoint = string.Format("inproc://{0}", ZContext.Encoding.GetString(rnd0)); 52 | } 53 | 54 | /// 55 | /// You are using ZContext.Current! 56 | /// 57 | public ZActor(string endpoint, ZAction0 action, params object[] args) 58 | : base() 59 | { 60 | this.Context = ZContext.Current; 61 | 62 | this.Endpoint = endpoint; 63 | this.Action0 = action; 64 | this.Arguments = args; 65 | } 66 | 67 | protected override void Run() 68 | { 69 | using (Backend = ZSocket.Create(Context, ZSocketType.PAIR)) 70 | { 71 | Backend.Bind(Endpoint); 72 | 73 | if (Action0 != null) 74 | { 75 | Action0(Backend, Cancellor, Arguments); 76 | } 77 | if (Action != null) 78 | { 79 | Action(Context, Backend, Cancellor, Arguments); 80 | } 81 | } 82 | } 83 | 84 | public override void Start() 85 | { 86 | base.Start(); 87 | 88 | if (Frontend == null) 89 | { 90 | Frontend = ZSocket.Create(Context, ZSocketType.PAIR); 91 | Frontend.Connect(Endpoint); 92 | } 93 | } 94 | 95 | protected override void Dispose(bool disposing) 96 | { 97 | base.Dispose(disposing); 98 | 99 | if (disposing) 100 | { 101 | if (Frontend != null) 102 | { 103 | Frontend.Dispose(); 104 | Frontend = null; 105 | } 106 | if (Backend != null) 107 | { 108 | Backend.Dispose(); 109 | Backend = null; 110 | } 111 | } 112 | } 113 | } 114 | } -------------------------------------------------------------------------------- /ZContextOption.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace ZeroMQ 8 | { 9 | public enum ZContextOption : int 10 | { 11 | IO_THREADS = 1, 12 | MAX_SOCKETS = 2, 13 | SOCKET_LIMIT = 3, 14 | THREAD_PRIORITY = 3, 15 | THREAD_SCHED_POLICY = 4, 16 | IPV6 = 42 // in zmq.h ZMQ_IPV6 is in the socket options section 17 | } 18 | } -------------------------------------------------------------------------------- /ZException.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ 2 | { 3 | using System; 4 | using System.Runtime.Serialization; 5 | 6 | using lib; 7 | using System.Runtime.InteropServices; 8 | 9 | /// 10 | /// An exception thrown by the result of libzmq. 11 | /// 12 | [Serializable] 13 | public class ZException : Exception 14 | { 15 | private ZError _error; 16 | 17 | /// 18 | /// Gets the error code returned by libzmq. 19 | /// 20 | [Obsolete("Use Error property instead")] 21 | public int ErrNo 22 | { 23 | // TODO why is "0" the default? 24 | get { return _error != null ? _error.Number : 0; } 25 | } 26 | /// 27 | /// Gets the error code returned by libzmq. 28 | /// 29 | [Obsolete("Use Error property instead")] 30 | public string ErrName 31 | { 32 | get 33 | { 34 | return _error != null ? _error.Name : string.Empty; 35 | } 36 | } 37 | 38 | /// 39 | /// Gets the error text returned by libzmq. 40 | /// 41 | [Obsolete("Use Error property instead")] 42 | public string ErrText 43 | { 44 | get 45 | { 46 | return _error != null ? _error.Text : string.Empty; 47 | } 48 | } 49 | 50 | public ZError Error 51 | { 52 | get { return _error; } 53 | } 54 | 55 | /// 56 | /// Initializes a new instance of the class. 57 | /// 58 | /// The error code returned by the ZeroMQ library call. 59 | protected ZException() 60 | { } 61 | 62 | /// 63 | /// Initializes a new instance of the class. 64 | /// 65 | /// The error code returned by the ZeroMQ library call. 66 | public ZException(ZError errorSymbol) 67 | : this(errorSymbol, default(string), default(Exception)) 68 | { } 69 | 70 | /// 71 | /// Initializes a new instance of the class. 72 | /// 73 | /// The error code returned by the ZeroMQ library call. 74 | public ZException(ZError errorSymbol, string message) 75 | : this(errorSymbol, message, default(Exception)) 76 | { } 77 | 78 | public ZException(ZError errorSymbol, string message, Exception inner) 79 | : base(MakeMessage(errorSymbol, message), inner) 80 | { 81 | this._error = errorSymbol; 82 | } 83 | 84 | static string MakeMessage(ZError error, string additionalMessage) 85 | { 86 | return error != null 87 | ? (string.IsNullOrEmpty(additionalMessage) 88 | ? error.ToString() 89 | : string.Format("{0}: {1}", error, additionalMessage)) 90 | : additionalMessage; 91 | } 92 | 93 | public override string ToString() 94 | { 95 | return Message; 96 | } 97 | 98 | /// 99 | /// Initializes a new instance of the class. 100 | /// 101 | /// that holds the serialized object data about the exception being thrown. 102 | /// that contains contextual information about the source or destination. 103 | protected ZException(SerializationInfo info, StreamingContext context) 104 | : base(info, context) 105 | { } 106 | 107 | } 108 | } -------------------------------------------------------------------------------- /ZFrameOption.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace ZeroMQ 8 | { 9 | public enum ZFrameOption : int 10 | { 11 | MORE = 1, 12 | SRCFD = 2, 13 | SHARED = 3, 14 | } 15 | } -------------------------------------------------------------------------------- /ZGuideExamples/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle("ZGuideExamples")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("")] 12 | [assembly: AssemblyCopyright("metadings")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion("1.0.*")] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | //[assembly: AssemblyDelaySign(false)] 26 | //[assembly: AssemblyKeyFile("")] 27 | 28 | -------------------------------------------------------------------------------- /ZGuideExamples/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | // INFO: You will find a "static int Main(string[] args)" in ProgramRunner.cs 14 | 15 | public static bool Verbose = false; 16 | 17 | static void Console_WriteZFrame(string format, ZFrame frame, params object[] data) 18 | { 19 | var renderer = new StringBuilder(); 20 | 21 | var list = new List(data); 22 | 23 | // here the renderer 24 | 25 | renderer.Append(format); 26 | renderer.Append(": "); 27 | renderer.Append("{"); 28 | renderer.Append(0 + data.Length); 29 | renderer.Append("}"); 30 | 31 | // now the message 32 | 33 | frame.Position = 0; 34 | 35 | if (frame.Length == 0) 36 | list.Add("0"); 37 | else 38 | list.Add(frame.ReadString()); 39 | 40 | frame.Position = 0; 41 | 42 | Console.WriteLine(renderer.ToString(), list.ToArray()); 43 | } 44 | 45 | static void Console_WriteZMessage(string format, ZMessage message, params object[] data) 46 | { 47 | Console_WriteZMessage(format, 0, message, data); 48 | } 49 | 50 | static void Console_WriteZMessage(string format, int messagesNotToRead, ZMessage message, params object[] data) 51 | { 52 | var renderer = new StringBuilder(); 53 | 54 | var list = new List(data); 55 | 56 | for (int i = messagesNotToRead, c = message.Count; i < c; ++i) 57 | { 58 | // here the renderer 59 | if (i == messagesNotToRead) 60 | { 61 | renderer.Append(format); 62 | renderer.Append(": "); 63 | } 64 | else 65 | { 66 | renderer.Append(", "); 67 | } 68 | renderer.Append("{"); 69 | renderer.Append( (i - messagesNotToRead) + data.Length ); 70 | renderer.Append("}"); 71 | 72 | // now the message 73 | ZFrame frame = message[i]; 74 | 75 | frame.Position = 0; 76 | 77 | if (frame.Length == 0) 78 | list.Add("0"); 79 | else 80 | list.Add(frame.ReadString()); 81 | 82 | frame.Position = 0; 83 | } 84 | 85 | Console.WriteLine(renderer.ToString(), list.ToArray()); 86 | } 87 | } 88 | 89 | public static class Ext { 90 | 91 | public static string ToHexString(this byte[] hex) { 92 | if (hex == null) { 93 | return null; 94 | } 95 | if (hex.Length == 0) { 96 | return string.Empty; 97 | } 98 | var s = new StringBuilder(); 99 | foreach (byte b in hex) { 100 | s.Append(b.ToString("x2")); 101 | } 102 | return s.ToString(); 103 | } 104 | 105 | public static byte[] ToHexBytes(this string hex) 106 | { 107 | if (hex == null) { 108 | return null; 109 | } 110 | if (hex.Length == 0) { 111 | return new byte[0]; 112 | } 113 | int l = hex.Length / 2; 114 | var b = new byte[l]; 115 | for (int i = 0; i < l; ++i) { 116 | b[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16); 117 | } 118 | return b; 119 | } 120 | } 121 | } -------------------------------------------------------------------------------- /ZGuideExamples/Z85Encode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | 5 | using ZeroMQ; 6 | 7 | namespace Examples 8 | { 9 | public partial class Program 10 | { 11 | public static void Z85Encode(string[] args) 12 | { 13 | // 14 | // Author: metadings 15 | // 16 | 17 | if (args == null || args.Length < 1) 18 | { 19 | args = new string[] { "Hello World!" }; 20 | } 21 | 22 | string txt = args[0]; 23 | string encoded = Z85.Encode(txt); 24 | Console.WriteLine("{0}: {1}", txt, encoded); 25 | } 26 | 27 | public static void Z85Decode(string[] args) 28 | { 29 | // 30 | // Author: metadings 31 | // 32 | 33 | if (args == null || args.Length < 1) 34 | { 35 | args = new string[] { "nm=QNzY&b1A+]nf" }; 36 | } 37 | 38 | string txt = args[0]; 39 | string decoded = Z85.Decode(txt); 40 | Console.WriteLine("{0}: {1}", txt, decoded); 41 | } 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /ZGuideExamples/ZGuideExamples.mono.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {EF3A0578-42E7-42D2-9D1D-1DF526FE97AB} 7 | Exe 8 | ZGuideExamples 9 | ZGuideExamples 10 | 11 | 12 | true 13 | pdbonly 14 | false 15 | ..\bin\Debug 16 | DEBUG; 17 | prompt 18 | 4 19 | true 20 | 21 | 22 | true 23 | ..\bin\Release 24 | prompt 25 | 4 26 | true 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | {6FFD872F-A4A4-4EFA-9B4D-4342BA6CF250} 109 | ZeroMQ.mono 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /ZGuideExamples/ZGuideExamples.netcore.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.2 5 | 6 | false 7 | Exe 8 | ZGuideExamples 9 | ZGuideExamples 10 | $(DefaultItemExcludes);AssemblyInfo.cs 11 | 12 | 13 | 14 | ..\bin\Debug 15 | 16 | 17 | ..\bin\Release 18 | 19 | 20 | 21 | false 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /ZGuideExamples/eagain.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void EAgain(string[] args) 14 | { 15 | // 16 | // Shows how to provoke EAGAIN when reaching HWM 17 | // 18 | // Author: metadings 19 | // 20 | 21 | using (var context = new ZContext()) 22 | using (var mailbox = new ZSocket(context, ZSocketType.DEALER)) 23 | { 24 | mailbox.SendHighWatermark = 4; 25 | mailbox.SendTimeout = TimeSpan.Zero; 26 | mailbox.Linger = TimeSpan.Zero; 27 | mailbox.Connect("tcp://127.0.0.1:9876"); 28 | 29 | ZError error; 30 | for (int count = 0; count < 10; ++count) 31 | { 32 | Console.WriteLine("Sending {0}. message", count); 33 | 34 | using (var outgoing = new ZFrame(string.Format("message {0}", count))) 35 | { 36 | if (!mailbox.Send(outgoing, ZSocketFlags.DontWait, out error)) 37 | { 38 | if (error == ZError.EAGAIN) 39 | { 40 | Console.WriteLine(new ZException(error)); 41 | break; 42 | 43 | /* Usually when reaching EAGAIN, I would do 44 | Thread.Sleep(1); 45 | continue; /**/ 46 | } 47 | if (error == ZError.ETERM) 48 | return; // Interrupted 49 | throw new ZException(error); 50 | } 51 | } 52 | } 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /ZGuideExamples/espresso.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void Espresso(string[] args) 14 | { 15 | // 16 | // Espresso Pattern 17 | // This shows how to capture data using a pub-sub proxy 18 | // 19 | // Author: metadings 20 | // 21 | 22 | using (var context = new ZContext()) 23 | using (var subscriber = new ZSocket(context, ZSocketType.XSUB)) 24 | using (var publisher = new ZSocket(context, ZSocketType.XPUB)) 25 | using (var listener = new ZSocket(context, ZSocketType.PAIR)) 26 | { 27 | new Thread(() => Espresso_Publisher(context)).Start(); 28 | new Thread(() => Espresso_Subscriber(context)).Start(); 29 | new Thread(() => Espresso_Listener(context)).Start(); 30 | 31 | subscriber.Connect("tcp://127.0.0.1:6000"); 32 | publisher.Bind("tcp://*:6001"); 33 | listener.Bind("inproc://listener"); 34 | 35 | ZError error; 36 | if (!ZContext.Proxy(subscriber, publisher, listener, out error)) 37 | { 38 | if (error == ZError.ETERM) 39 | return; // Interrupted 40 | throw new ZException(error); 41 | } 42 | } 43 | } 44 | 45 | static void Espresso_Publisher(ZContext context) 46 | { 47 | // The publisher sends random messages starting with A-J: 48 | 49 | using (var publisher = new ZSocket(context, ZSocketType.PUB)) 50 | { 51 | publisher.Bind("tcp://*:6000"); 52 | 53 | ZError error; 54 | 55 | while (true) 56 | { 57 | var frame = ZFrame.Create(8); 58 | var bytes = new byte[8]; 59 | using (var rng = new System.Security.Cryptography.RNGCryptoServiceProvider()) 60 | { 61 | rng.GetBytes(bytes); 62 | } 63 | frame.Write(bytes, 0, 8); 64 | 65 | if (!publisher.SendFrame(frame, out error)) 66 | { 67 | if (error == ZError.ETERM) 68 | return; // Interrupted 69 | throw new ZException(error); 70 | } 71 | 72 | Thread.Sleep(1); 73 | } 74 | } 75 | } 76 | 77 | static void Espresso_Subscriber(ZContext context) 78 | { 79 | // The subscriber thread requests messages starting with 80 | // A and B, then reads and counts incoming messages. 81 | 82 | using (var subscriber = new ZSocket(context, ZSocketType.SUB)) 83 | { 84 | subscriber.Connect("tcp://127.0.0.1:6001"); 85 | subscriber.Subscribe("A"); 86 | subscriber.Subscribe("B"); 87 | 88 | ZError error; 89 | ZFrame frame; 90 | int count = 0; 91 | while (count < 5) 92 | { 93 | if (null == (frame = subscriber.ReceiveFrame(out error))) 94 | { 95 | if (error == ZError.ETERM) 96 | return; // Interrupted 97 | throw new ZException(error); 98 | } 99 | 100 | ++count; 101 | } 102 | 103 | Console.WriteLine("I: subscriber counted {0}", count); 104 | } 105 | } 106 | 107 | static void Espresso_Listener(ZContext context) 108 | { 109 | // The listener receives all messages flowing through the proxy, on its 110 | // pipe. In CZMQ, the pipe is a pair of ZMQ_PAIR sockets that connect 111 | // attached child threads. In other languages your mileage may vary: 112 | 113 | using (var listener = new ZSocket(context, ZSocketType.PAIR)) 114 | { 115 | listener.Connect("inproc://listener"); 116 | 117 | ZError error; 118 | ZFrame frame; 119 | while (true) 120 | { 121 | if (null != (frame = listener.ReceiveFrame(out error))) 122 | { 123 | using (frame) 124 | { 125 | byte first = frame.ReadAsByte(); 126 | 127 | var rest = new byte[9]; 128 | frame.Read(rest, 0, rest.Length); 129 | 130 | Console.WriteLine("{0} {1}", (char)first, rest.ToHexString()); 131 | 132 | if (first == 0x01) 133 | { 134 | // Subscribe 135 | } 136 | else if (first == 0x00) 137 | { 138 | // Unsubscribe 139 | context.Shutdown(); 140 | } 141 | } 142 | } 143 | else 144 | { 145 | if (error == ZError.ETERM) 146 | return; // Interrupted 147 | throw new ZException(error); 148 | } 149 | } 150 | } 151 | } 152 | } 153 | } -------------------------------------------------------------------------------- /ZGuideExamples/flclient1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | static readonly TimeSpan FLClient1_REQUEST_TIMEOUT = TimeSpan.FromMilliseconds(2500); 14 | 15 | static int FLClient1_MAX_RETRIES = 3; // Before we abandon 16 | 17 | public static void FLClient1(string[] args) 18 | { 19 | // 20 | // Freelance client - Model 1 21 | // Uses REQ socket to query one or more services 22 | // 23 | // Author: metadings 24 | // 25 | 26 | if (args == null || args.Length < 1) 27 | { 28 | Console.WriteLine(); 29 | Console.WriteLine("Usage: ./{0} FLClient1 [Endpoint]", AppDomain.CurrentDomain.FriendlyName); 30 | Console.WriteLine(); 31 | Console.WriteLine(" Endpoint Where FLClient1 should connect to."); 32 | Console.WriteLine(" Default is tcp://127.0.0.1:7780"); 33 | Console.WriteLine(); 34 | args = new string[] { "tcp://127.0.0.1:7780" }; 35 | } 36 | 37 | // The client uses a Lazy Pirate strategy if it only has one server to talk 38 | // to. If it has two or more servers to talk to, it will try each server just 39 | // once: 40 | 41 | using (var context = new ZContext()) 42 | using (var request = new ZFrame("Hello World")) 43 | { 44 | ZFrame reply = null; 45 | 46 | if (args.Length == 1) 47 | { 48 | // For one endpoint, we retry N times 49 | string endpoint = args[0]; 50 | 51 | for (int retries = 0; retries < FLClient1_MAX_RETRIES; ++retries) 52 | { 53 | if (null != (reply = FLClient1_TryRequest(context, endpoint, request))) 54 | { 55 | break; // Successful 56 | } 57 | Console.WriteLine("W: no response from {0}, retrying...", endpoint); 58 | } 59 | } 60 | else 61 | { 62 | // For multiple endpoints, try each at most once 63 | 64 | for (int endpoint_nbr = 0; endpoint_nbr < args.Length; ++endpoint_nbr) 65 | { 66 | string endpoint = args[endpoint_nbr]; 67 | 68 | if (null != (reply = FLClient1_TryRequest(context, endpoint, request))) 69 | { 70 | break; // Successful 71 | } 72 | Console.WriteLine("W: no response from {0}, retrying...", endpoint); 73 | } 74 | } 75 | 76 | if (reply != null) 77 | { 78 | Console.WriteLine("Service is running OK"); 79 | } 80 | } 81 | } 82 | 83 | static ZFrame FLClient1_TryRequest(ZContext context, string endpoint, ZFrame request) 84 | { 85 | Console.WriteLine("I: trying echo service at {0}...", endpoint); 86 | 87 | using (var client = new ZSocket(context, ZSocketType.REQ)) 88 | { 89 | client.Connect(endpoint); 90 | 91 | // Send request, wait safely for reply 92 | using (var message = ZFrame.CopyFrom(request)) 93 | { 94 | client.Send(message); 95 | } 96 | 97 | var poll = ZPollItem.CreateReceiver(); 98 | ZError error; 99 | ZMessage incoming; 100 | 101 | if (client.PollIn(poll, out incoming, out error, FLClient1_REQUEST_TIMEOUT)) 102 | { 103 | return incoming[0]; 104 | } 105 | } 106 | return null; 107 | } 108 | } 109 | } -------------------------------------------------------------------------------- /ZGuideExamples/flclient3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading; 7 | 8 | using ZeroMQ; 9 | 10 | namespace Examples 11 | { 12 | using FLCliApi; // Lets us build this source without creating a library 13 | 14 | static partial class Program 15 | { 16 | 17 | public static void FLClient3(string[] args) 18 | { 19 | // 20 | // Freelance client - Model 3 21 | // Uses FLCliApi.FreelanceClient class to encapsulate Freelance pattern 22 | // 23 | // Author: metadings 24 | // 25 | if (args == null || args.Length < 2) 26 | { 27 | Console.WriteLine(); 28 | Console.WriteLine("Usage: ./{0} FLClient3 [Name] [Endpoint]", AppDomain.CurrentDomain.FriendlyName); 29 | Console.WriteLine(); 30 | Console.WriteLine(" Name Your Name"); 31 | Console.WriteLine(" Endpoint Where FLClient3 should connect to."); 32 | Console.WriteLine(" Default: tcp://127.0.0.1:5555"); 33 | Console.WriteLine(); 34 | if (args.Length < 1) 35 | args = new string[] { "World", "tcp://127.0.0.1:5555" }; 36 | else 37 | args = new string[] { args[0], "tcp://127.0.0.1:5555" }; 38 | } 39 | 40 | string name = args[0]; 41 | 42 | // Create new freelance client object 43 | using (var client = new FreelanceClient()) 44 | { 45 | // Connect to one or more endpoints 46 | for (int i = 0; i < args.Length - 1; ++i) 47 | { 48 | client.Connect(args[1]); 49 | } 50 | 51 | // Send a bunch of name resolution 'requests', measure time 52 | var stopwatch = new Stopwatch(); 53 | stopwatch.Start(); 54 | 55 | int requests = 0; 56 | while (requests++ < 100) 57 | { 58 | using (var request = new ZMessage()) 59 | { 60 | request.Add(new ZFrame(name)); 61 | 62 | using (ZMessage reply = client.Request(request)) 63 | { 64 | 65 | } 66 | } 67 | } 68 | 69 | stopwatch.Stop(); 70 | Console.WriteLine("Average round trip cost: {0} ms", stopwatch.ElapsedMilliseconds / requests); 71 | } 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /ZGuideExamples/flserver1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void FLServer1(string[] args) 14 | { 15 | // 16 | // Freelance server - Model 1 17 | // Trivial echo service 18 | // 19 | // Author: metadings 20 | // 21 | 22 | if (args == null || args.Length < 1) 23 | { 24 | Console.WriteLine(); 25 | Console.WriteLine("Usage: ./{0} FLServer1 [Endpoint]", AppDomain.CurrentDomain.FriendlyName); 26 | Console.WriteLine(); 27 | Console.WriteLine(" Endpoint Where FLServer1 should bind on."); 28 | Console.WriteLine(" Default is tcp://127.0.0.1:7780"); 29 | Console.WriteLine(); 30 | args = new string[] { "tcp://127.0.0.1:7780" }; 31 | } 32 | 33 | using (var context = new ZContext()) 34 | using (var server = new ZSocket(context, ZSocketType.REP)) 35 | { 36 | server.Bind(args[0]); 37 | 38 | Console.WriteLine("I: echo service is ready at {0}", args[0]); 39 | 40 | ZMessage message; 41 | ZError error; 42 | while (true) 43 | { 44 | if (null != (message = server.ReceiveMessage(out error))) 45 | { 46 | using (message) 47 | { 48 | server.Send(message); 49 | } 50 | } 51 | else 52 | { 53 | if (error == ZError.ETERM) 54 | return; // Interrupted 55 | throw new ZException(error); 56 | } 57 | } 58 | } 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /ZGuideExamples/flserver2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void FLServer2(string[] args) 14 | { 15 | // 16 | // Freelance server - Model 2 17 | // Does some work, replies OK, with message sequencing 18 | // 19 | // Author: metadings 20 | // 21 | 22 | if (args == null || args.Length < 1) 23 | { 24 | Console.WriteLine(); 25 | Console.WriteLine("Usage: ./{0} FLServer2 [Endpoint]", AppDomain.CurrentDomain.FriendlyName); 26 | Console.WriteLine(); 27 | Console.WriteLine(" Endpoint Where FLServer2 should bind on."); 28 | Console.WriteLine(" Default is tcp://127.0.0.1:7781"); 29 | Console.WriteLine(); 30 | args = new string[] { "tcp://127.0.0.1:7781" }; 31 | } 32 | 33 | string endpoint = args[0]; 34 | 35 | using (var context = new ZContext()) 36 | using (var server = new ZSocket(context, ZSocketType.REP)) 37 | { 38 | server.Bind(endpoint); 39 | Console.WriteLine("I: server is ready as {0}", endpoint); 40 | 41 | ZError error; 42 | ZMessage incoming; 43 | 44 | while (true) 45 | { 46 | if (null == (incoming = server.ReceiveMessage(out error))) 47 | { 48 | if (error == ZError.ETERM) 49 | break; // Interrupted 50 | throw new ZException(error); 51 | } 52 | 53 | ZFrame identity; 54 | using (incoming) 55 | { 56 | // Fail nastily if run against wrong client 57 | if (incoming.Count < 2) 58 | { 59 | throw new InvalidOperationException(); 60 | } 61 | 62 | identity = incoming.RemoveAt(0, false); 63 | } 64 | using (identity) 65 | using (var outgoing = new ZMessage()) 66 | { 67 | outgoing.Add(identity); 68 | outgoing.Add(new ZFrame("OK")); 69 | 70 | if (!server.Send(outgoing, out error)) 71 | { 72 | if (error == ZError.ETERM) 73 | break; // Interrupted 74 | throw new ZException(error); 75 | } 76 | } 77 | } 78 | 79 | if (error == ZError.ETERM) 80 | { 81 | Console.WriteLine("W: interrupted"); 82 | } 83 | } 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /ZGuideExamples/flserver3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void FLServer3(string[] args) 14 | { 15 | // 16 | // Freelance server - Model 3 17 | // Uses an ROUTER/ROUTER socket but just one thread 18 | // 19 | // Author: metadings 20 | // 21 | 22 | // Prepare server socket with predictable identity 23 | string bind_endpoint = "tcp://*:5555"; 24 | string connect_endpoint = "tcp://127.0.0.1:5555"; 25 | 26 | using (var context = new ZContext()) 27 | using (var server = new ZSocket(context, ZSocketType.ROUTER)) 28 | { 29 | Console.CancelKeyPress += (s, ea) => 30 | { 31 | ea.Cancel = true; 32 | context.Shutdown(); 33 | }; 34 | 35 | server.IdentityString = connect_endpoint; 36 | server.Bind(bind_endpoint); 37 | Console.WriteLine("I: service is ready as {0}", bind_endpoint); 38 | 39 | ZError error; 40 | ZMessage request; 41 | while (true) 42 | { 43 | if (null == (request = server.ReceiveMessage(out error))) 44 | { 45 | if (error == ZError.ETERM) 46 | break; // Interrupted 47 | throw new ZException(error); 48 | } 49 | using (var response = new ZMessage()) 50 | { 51 | ZFrame identity; 52 | 53 | using (request) 54 | { 55 | if (Verbose) Console_WriteZMessage("Receiving", request); 56 | 57 | // Frame 0: identity of client 58 | // Frame 1: PING, or client control frame 59 | // Frame 2: request body 60 | 61 | identity = request.Pop(); 62 | 63 | ZFrame control = request.Pop(); 64 | string controlMessage = control.ReadString(); 65 | 66 | if (controlMessage == "PING") 67 | { 68 | control.Dispose(); 69 | response.Add(new ZFrame("PONG")); 70 | } 71 | else 72 | { 73 | response.Add(control); 74 | response.Add(new ZFrame("OK")); 75 | } 76 | } 77 | 78 | response.Prepend(identity); 79 | 80 | if (Verbose) Console_WriteZMessage("Sending ", response); 81 | if (!server.Send(response, out error)) 82 | { 83 | if (error == ZError.ETERM) 84 | break; // Interrupted 85 | throw new ZException(error); 86 | } 87 | } 88 | } 89 | if (error == ZError.ETERM) 90 | { 91 | Console.WriteLine("W: interrupted"); 92 | } 93 | } 94 | } 95 | 96 | } 97 | } -------------------------------------------------------------------------------- /ZGuideExamples/hwclient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void HWClient(string[] args) 14 | { 15 | // 16 | // Hello World client 17 | // 18 | // Author: metadings 19 | // 20 | 21 | if (args == null || args.Length < 1) 22 | { 23 | Console.WriteLine(); 24 | Console.WriteLine("Usage: ./{0} HWClient [Endpoint]", AppDomain.CurrentDomain.FriendlyName); 25 | Console.WriteLine(); 26 | Console.WriteLine(" Endpoint Where HWClient should connect to."); 27 | Console.WriteLine(" Default is tcp://127.0.0.1:5555"); 28 | Console.WriteLine(); 29 | args = new string[] { "tcp://127.0.0.1:5555" }; 30 | } 31 | 32 | string endpoint = args[0]; 33 | 34 | // Create 35 | using (var context = new ZContext()) 36 | using (var requester = new ZSocket(context, ZSocketType.REQ)) 37 | { 38 | // Connect 39 | requester.Connect(endpoint); 40 | 41 | for (int n = 0; n < 10; ++n) 42 | { 43 | string requestText = "Hello"; 44 | Console.Write("Sending {0}...", requestText); 45 | 46 | // Send 47 | requester.Send(new ZFrame(requestText)); 48 | 49 | // Receive 50 | using (ZFrame reply = requester.ReceiveFrame()) 51 | { 52 | Console.WriteLine(" Received: {0} {1}!", requestText, reply.ReadString()); 53 | } 54 | } 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /ZGuideExamples/hwserver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void HWServer(string[] args) 14 | { 15 | // 16 | // Hello World server 17 | // 18 | // Author: metadings 19 | // 20 | 21 | if (args == null || args.Length < 1) 22 | { 23 | Console.WriteLine(); 24 | Console.WriteLine("Usage: ./{0} HWServer [Name]", AppDomain.CurrentDomain.FriendlyName); 25 | Console.WriteLine(); 26 | Console.WriteLine(" Name Your name. Default: World"); 27 | Console.WriteLine(); 28 | args = new string[] { "World" }; 29 | } 30 | 31 | string name = args[0]; 32 | 33 | // Create 34 | using (var context = new ZContext()) 35 | using (var responder = new ZSocket(context, ZSocketType.REP)) 36 | { 37 | // Bind 38 | responder.Bind("tcp://*:5555"); 39 | 40 | while (true) 41 | { 42 | // Receive 43 | using (ZFrame request = responder.ReceiveFrame()) 44 | { 45 | Console.WriteLine("Received {0}", request.ReadString()); 46 | 47 | // Do some work 48 | Thread.Sleep(1); 49 | 50 | // Send 51 | responder.Send(new ZFrame(name)); 52 | } 53 | } 54 | } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /ZGuideExamples/identity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void Identity(string[] args) 14 | { 15 | // 16 | // Demonstrate request-reply identities 17 | // 18 | // Author: metadings 19 | // 20 | 21 | using (var context = new ZContext()) 22 | using (var sink = new ZSocket(context, ZSocketType.ROUTER)) 23 | { 24 | sink.Bind("inproc://example"); 25 | 26 | // First allow 0MQ to set the identity 27 | using (var anonymous = new ZSocket(context, ZSocketType.REQ)) 28 | { 29 | anonymous.Connect("inproc://example"); 30 | anonymous.Send(new ZFrame("ROUTER uses REQ's generated 5 byte identity")); 31 | } 32 | using (ZMessage msg = sink.ReceiveMessage()) 33 | { 34 | msg.DumpZmsg("--------------------------"); 35 | } 36 | 37 | // Then set the identity ourselves 38 | using (var identified = new ZSocket(context, ZSocketType.REQ)) 39 | { 40 | identified.IdentityString = "PEER2"; 41 | identified.Connect("inproc://example"); 42 | identified.Send(new ZFrame("ROUTER uses REQ's socket identity")); 43 | } 44 | using (ZMessage msg = sink.ReceiveMessage()) 45 | { 46 | msg.DumpZmsg("--------------------------"); 47 | } 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /ZGuideExamples/interrupt.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void Interrupt(string[] args) 14 | { 15 | // 16 | // Interrupt 17 | // 18 | // Author: metadings 19 | // 20 | 21 | if (args == null || args.Length == 0) 22 | { 23 | args = new string[] { "World" }; 24 | } 25 | 26 | string name = args[0]; 27 | 28 | var error = default(ZError); 29 | 30 | using (var context = new ZContext()) 31 | using (var responder = new ZSocket(context, ZSocketType.REP)) 32 | { 33 | Console.CancelKeyPress += (s, ea) => 34 | { 35 | ea.Cancel = true; 36 | context.Shutdown(); 37 | }; 38 | 39 | responder.Bind("tcp://*:5555"); 40 | 41 | ZFrame request; 42 | 43 | while (true) 44 | { 45 | if (Console.KeyAvailable) 46 | { 47 | ConsoleKeyInfo info = Console.ReadKey(true); 48 | /* if (info.Modifiers == ConsoleModifiers.Control && info.Key == ConsoleKey.C) 49 | { 50 | context.Shutdown(); 51 | } /**/ 52 | if (info.Key == ConsoleKey.Escape) 53 | { 54 | context.Shutdown(); 55 | } 56 | } 57 | 58 | if (null == (request = responder.ReceiveFrame(ZSocketFlags.DontWait, out error))) 59 | { 60 | if (error == ZError.EAGAIN) 61 | { 62 | Thread.Sleep(1); 63 | continue; 64 | } 65 | if (error == ZError.ETERM) 66 | break; // Interrupted 67 | throw new ZException(error); 68 | } 69 | 70 | using (request) 71 | { 72 | Console.Write("Received: {0}!", request.ReadString()); 73 | 74 | Thread.Sleep(512); // See also the much slower reaction 75 | 76 | Console.WriteLine(" Sending {0}... ", name); 77 | 78 | if (!responder.Send(new ZFrame(name), out error)) 79 | { 80 | if (error == ZError.ETERM) 81 | break; // Interrupted 82 | throw new ZException(error); 83 | } 84 | } 85 | } 86 | 87 | if (error == ZError.ETERM) 88 | { 89 | Console.WriteLine("Terminated! You have pressed CTRL+C or ESC."); 90 | return; 91 | } 92 | throw new ZException(error); 93 | } 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /ZGuideExamples/ironhouseclient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void IronhouseClient(string[] args) 14 | { 15 | // 16 | // Hello World client with ironhouse security 17 | // 18 | // Author: hawkans 19 | // 20 | 21 | if (args == null || args.Length < 1) 22 | { 23 | Console.WriteLine(); 24 | Console.WriteLine("Usage: ./{0} Ironhouse HWClient [Endpoint]", AppDomain.CurrentDomain.FriendlyName); 25 | Console.WriteLine(); 26 | Console.WriteLine(" Endpoint Where HWClient should connect to."); 27 | Console.WriteLine(" Default is tcp://127.0.0.1:5555"); 28 | Console.WriteLine(); 29 | args = new string[] { "tcp://127.0.0.1:5555" }; 30 | } 31 | 32 | string endpoint = args[0]; 33 | 34 | // Create 35 | 36 | using (var context = new ZContext()) 37 | using (var requester = new ZSocket(context, ZSocketType.REQ)) 38 | { 39 | ZCert clientCert = GetOrCreateCert("clienttest", ".curve"); 40 | ZCert serverCert = GetOrCreateCert("servertest"); 41 | requester.CurvePublicKey = clientCert.PublicKey; 42 | requester.CurveSecretKey = clientCert.SecretKey; 43 | requester.CurveServer = true; 44 | requester.CurveServerKey = serverCert.PublicKey; 45 | // Connect 46 | requester.Connect(endpoint); 47 | 48 | for (int n = 0; n < 10; ++n) 49 | { 50 | string requestText = "Hello"; 51 | Console.Write("Sending {0}...", requestText); 52 | 53 | // Send 54 | requester.Send(new ZFrame(requestText)); 55 | 56 | // Receive 57 | using (ZFrame reply = requester.ReceiveFrame()) 58 | { 59 | Console.WriteLine(" Received: {0} {1}!", requestText, reply.ReadString()); 60 | } 61 | } 62 | } 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /ZGuideExamples/ironhouseserver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading; 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void IronhouseServer(string[] args) 14 | { 15 | // 16 | // Hello World server with ironhouse security 17 | // 18 | // Author: hawkans 19 | // 20 | 21 | if (args == null || args.Length < 1) 22 | { 23 | Console.WriteLine(); 24 | Console.WriteLine("Usage: ./{0} Ironhouse HWServer [Name]", AppDomain.CurrentDomain.FriendlyName); 25 | Console.WriteLine(); 26 | Console.WriteLine(" Name Your name. Default: World"); 27 | Console.WriteLine(); 28 | args = new string[] { "World" }; 29 | } 30 | 31 | string name = args[0]; 32 | // Create or load certificates 33 | ZCert clientCert = GetOrCreateCert("clienttest"); 34 | ZCert serverCert = GetOrCreateCert("servertest"); 35 | 36 | using (var responder = new ZSocket(ZSocketType.REP)) 37 | using (var actor = new ZActor(ZAuth.Action0, null)) 38 | { 39 | actor.Start(); 40 | // send CURVE settings to ZAuth 41 | actor.Frontend.Send(new ZFrame("VERBOSE")); 42 | actor.Frontend.Send(new ZMessage(new List() 43 | { new ZFrame("ALLOW"), new ZFrame("127.0.0.1") } )); 44 | actor.Frontend.Send(new ZMessage(new List() 45 | { new ZFrame("CURVE"), new ZFrame(".curve") })); 46 | 47 | responder.CurvePublicKey = serverCert.PublicKey; 48 | responder.CurveSecretKey = serverCert.SecretKey; 49 | responder.CurveServer = true; 50 | // Bind 51 | responder.Bind("tcp://*:5555"); 52 | 53 | while (true) 54 | { 55 | // Receive 56 | using (ZFrame request = responder.ReceiveFrame()) 57 | { 58 | Console.WriteLine("Received {0}", request.ReadString()); 59 | 60 | // Do some work 61 | Thread.Sleep(1); 62 | 63 | // Send 64 | responder.Send(new ZFrame(name)); 65 | } 66 | } 67 | } 68 | } 69 | 70 | private static ZCert GetOrCreateCert(string name, string curvpath = ".curve") 71 | { 72 | ZCert cert; 73 | string keyfile = Path.Combine(curvpath, name + ".pub"); 74 | if (!File.Exists(keyfile)) 75 | { 76 | cert = new ZCert(); 77 | Directory.CreateDirectory(curvpath); 78 | cert.SetMeta("name", name); 79 | cert.Save(keyfile); 80 | } 81 | else 82 | { 83 | cert = ZCert.Load(keyfile); 84 | } 85 | return cert; 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /ZGuideExamples/lpclient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | // 14 | // Lazy Pirate client 15 | // Use zmq_poll (pollItem.PollIn) to do a safe request-reply 16 | // To run, start lpserver and then randomly kill/restart it 17 | // 18 | // Author: metadings 19 | // 20 | 21 | static TimeSpan LPClient_RequestTimeout = TimeSpan.FromMilliseconds(2000); 22 | static int LPClient_RequestRetries = 3; 23 | 24 | static ZSocket LPClient_CreateZSocket(ZContext context, string name, out ZError error) 25 | { 26 | // Helper function that returns a new configured socket 27 | // connected to the Lazy Pirate queue 28 | 29 | var requester = new ZSocket(context, ZSocketType.REQ); 30 | requester.IdentityString = name; 31 | requester.Linger = TimeSpan.FromMilliseconds(1); 32 | 33 | if (!requester.Connect("tcp://127.0.0.1:5555", out error)) 34 | { 35 | return null; 36 | } 37 | return requester; 38 | } 39 | 40 | public static void LPClient(string[] args) 41 | { 42 | if (args == null || args.Length < 1) 43 | { 44 | Console.WriteLine(); 45 | Console.WriteLine("Usage: ./{0} LPClient [Name]", AppDomain.CurrentDomain.FriendlyName); 46 | Console.WriteLine(); 47 | Console.WriteLine(" Name Your name. Default: People"); 48 | Console.WriteLine(); 49 | args = new string[] { "People" }; 50 | } 51 | 52 | string name = args[0]; 53 | 54 | using (var context = new ZContext()) 55 | { 56 | ZSocket requester = null; 57 | try 58 | { // using (requester) 59 | 60 | ZError error; 61 | 62 | if (null == (requester = LPClient_CreateZSocket(context, name, out error))) 63 | { 64 | if (error == ZError.ETERM) 65 | return; // Interrupted 66 | throw new ZException(error); 67 | } 68 | 69 | int sequence = 0; 70 | int retries_left = LPClient_RequestRetries; 71 | var poll = ZPollItem.CreateReceiver(); 72 | 73 | while (retries_left > 0) 74 | { 75 | // We send a request, then we work to get a reply 76 | using (var outgoing = ZFrame.Create(4)) 77 | { 78 | outgoing.Write(++sequence); 79 | if (!requester.Send(outgoing, out error)) 80 | { 81 | if (error == ZError.ETERM) 82 | return; // Interrupted 83 | throw new ZException(error); 84 | } 85 | } 86 | 87 | ZMessage incoming; 88 | while (true) 89 | { 90 | // Here we process a server reply and exit our loop 91 | // if the reply is valid. 92 | 93 | // If we didn't a reply, we close the client socket 94 | // and resend the request. We try a number of times 95 | // before finally abandoning: 96 | 97 | // Poll socket for a reply, with timeout 98 | if (requester.PollIn(poll, out incoming, out error, LPClient_RequestTimeout)) 99 | { 100 | using (incoming) 101 | { 102 | // We got a reply from the server 103 | int incoming_sequence = incoming[0].ReadInt32(); 104 | if (sequence == incoming_sequence) 105 | { 106 | Console.WriteLine("I: server replied OK ({0})", incoming_sequence); 107 | retries_left = LPClient_RequestRetries; 108 | break; 109 | } 110 | else 111 | { 112 | Console_WriteZMessage("E: malformed reply from server", incoming); 113 | } 114 | } 115 | } 116 | else 117 | { 118 | if (error == ZError.EAGAIN) 119 | { 120 | if (--retries_left == 0) 121 | { 122 | Console.WriteLine("E: server seems to be offline, abandoning"); 123 | break; 124 | } 125 | 126 | Console.WriteLine("W: no response from server, retrying..."); 127 | 128 | // Old socket is confused; close it and open a new one 129 | requester.Dispose(); 130 | if (null == (requester = LPClient_CreateZSocket(context, name, out error))) 131 | { 132 | if (error == ZError.ETERM) 133 | return; // Interrupted 134 | throw new ZException(error); 135 | } 136 | 137 | Console.WriteLine("I: reconnected"); 138 | 139 | // Send request again, on new socket 140 | using (var outgoing = ZFrame.Create(4)) 141 | { 142 | outgoing.Write(sequence); 143 | if (!requester.Send(outgoing, out error)) 144 | { 145 | if (error == ZError.ETERM) 146 | return; // Interrupted 147 | throw new ZException(error); 148 | } 149 | } 150 | 151 | continue; 152 | } 153 | 154 | if (error == ZError.ETERM) 155 | return; // Interrupted 156 | throw new ZException(error); 157 | } 158 | } 159 | } 160 | } 161 | finally 162 | { 163 | if (requester != null) 164 | { 165 | requester.Dispose(); 166 | requester = null; 167 | } 168 | } 169 | } 170 | } 171 | } 172 | } -------------------------------------------------------------------------------- /ZGuideExamples/lpserver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | // 14 | // Lazy Pirate server 15 | // Binds REP socket to tcp://*:5555 16 | // Like hwserver except: 17 | // - echoes request as-is 18 | // - randomly runs slowly, or exits to simulate a crash. 19 | // 20 | // Author: metadings 21 | // 22 | 23 | public static void LPServer(string[] args) 24 | { 25 | using (var context = new ZContext()) 26 | using (var responder = new ZSocket(context, ZSocketType.REP)) 27 | { 28 | responder.Bind("tcp://*:5555"); 29 | 30 | ZError error; 31 | int cycles = 0; 32 | var rnd = new Random(); 33 | 34 | while (true) 35 | { 36 | ZMessage incoming; 37 | if (null == (incoming = responder.ReceiveMessage(out error))) 38 | { 39 | if (error == ZError.ETERM) 40 | return; // Interrupted 41 | throw new ZException(error); 42 | } 43 | using (incoming) 44 | { 45 | ++cycles; 46 | 47 | // Simulate various problems, after a few cycles 48 | if (cycles > 16 && rnd.Next(16) == 0) 49 | { 50 | Console.WriteLine("I: simulating a crash"); 51 | break; 52 | } 53 | else if (cycles > 4 && rnd.Next(4) == 0) 54 | { 55 | Console.WriteLine("I: simulating CPU overload"); 56 | Thread.Sleep(1000); 57 | } 58 | 59 | Console.WriteLine("I: normal request ({0})", incoming[0].ReadInt32()); 60 | 61 | Thread.Sleep(1); // Do some heavy work 62 | 63 | responder.Send(incoming); 64 | } 65 | } 66 | } 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /ZGuideExamples/lvcache.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void LVCache(string[] args) 14 | { 15 | // 16 | // Last value cache 17 | // Uses XPUB subscription messages to re-send data 18 | // 19 | // Author: metadings 20 | // 21 | 22 | using (var context = new ZContext()) 23 | using (var frontend = new ZSocket(context, ZSocketType.SUB)) 24 | using (var backend = new ZSocket(context, ZSocketType.XPUB)) 25 | { 26 | // Subscribe to every single topic from publisher 27 | frontend.Bind("tcp://*:5557"); 28 | frontend.SubscribeAll(); 29 | 30 | backend.Bind("tcp://*:5558"); 31 | 32 | // Store last instance of each topic in a cache 33 | var cache = new HashSet(); 34 | 35 | // We route topic updates from frontend to backend, and 36 | // we handle subscriptions by sending whatever we cached, 37 | // if anything: 38 | var p = ZPollItem.CreateReceiver(); 39 | ZMessage msg; 40 | ZError error; 41 | while (true) 42 | { 43 | // Any new topic data we cache and then forward 44 | if (frontend.PollIn(p, out msg, out error, TimeSpan.FromMilliseconds(1))) 45 | { 46 | using (msg) 47 | { 48 | string topic = msg[0].ReadString(); 49 | string current = msg[1].ReadString(); 50 | 51 | LVCacheItem previous = cache.FirstOrDefault(item => topic == item.Topic); 52 | if (previous != null) 53 | { 54 | cache.Remove(previous); 55 | } 56 | cache.Add(new LVCacheItem { Topic = topic, Current = current }); 57 | 58 | backend.Send(msg); 59 | } 60 | } 61 | else 62 | { 63 | if (error == ZError.ETERM) 64 | break; // Interrupted 65 | if (error != ZError.EAGAIN) 66 | throw new ZException(error); 67 | } 68 | 69 | // When we get a new subscription, we pull data from the cache: 70 | if (backend.PollIn(p, out msg, out error, TimeSpan.FromMilliseconds(1))) 71 | { 72 | using (msg) 73 | { 74 | // Event is one byte 0=unsub or 1=sub, followed by topic 75 | byte subscribe = msg[0].ReadAsByte(); 76 | if (subscribe == 0x01) 77 | { 78 | string topic = msg[0].ReadString(); 79 | LVCacheItem previous = cache.FirstOrDefault(item => topic == item.Topic); 80 | if (previous != null) 81 | { 82 | Console.WriteLine("Sending cached topic {0}", topic); 83 | backend.SendMore(new ZFrame(previous.Topic)); 84 | backend.Send(new ZFrame(previous.Current)); 85 | } 86 | else 87 | { 88 | Console.WriteLine("Failed to send cached topic {0}!", topic); 89 | } 90 | } 91 | } 92 | } 93 | else 94 | { 95 | if (error == ZError.ETERM) 96 | break; // Interrupted 97 | if (error != ZError.EAGAIN) 98 | throw new ZException(error); 99 | } 100 | } 101 | } 102 | } 103 | 104 | class LVCacheItem 105 | { 106 | public string Topic; 107 | public string Current; 108 | 109 | public override int GetHashCode() 110 | { 111 | return Topic.GetHashCode(); 112 | } 113 | } 114 | } 115 | } -------------------------------------------------------------------------------- /ZGuideExamples/mdclient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading; 4 | using ZeroMQ; 5 | 6 | namespace Examples 7 | { 8 | using MDCliApi; // Let us build this source without creating a library 9 | static partial class Program 10 | { 11 | // Majordomo Protocol client example 12 | // Uses the mdcli API to hide all MDP aspects 13 | public static void MDClient(string[] args) 14 | { 15 | CancellationTokenSource cts = new CancellationTokenSource(); 16 | Console.CancelKeyPress += (s, ea) => 17 | { 18 | ea.Cancel = true; 19 | cts.Cancel(); 20 | }; 21 | 22 | using (MajordomoClient session = new MajordomoClient("tcp://127.0.0.1:5555", Verbose)) 23 | { 24 | int count; 25 | for (count = 0; count < 100000; count++) 26 | { 27 | ZMessage request = new ZMessage(); 28 | request.Prepend(new ZFrame("Hello world")); 29 | using (ZMessage reply = session.Send("echo", request, cts)) 30 | if (reply == null) 31 | break; // Interrupt or failure 32 | } 33 | Console.WriteLine("{0} requests/replies processed\n", count); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /ZGuideExamples/mdclient2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading; 4 | using ZeroMQ; 5 | 6 | namespace Examples 7 | { 8 | using MDCliApi2; // Let us build this source without creating a library 9 | static partial class Program 10 | { 11 | // Majordomo Protocol client example 12 | // Uses the mdcli API to hide all MDP aspects 13 | public static void MDClient2(string[] args) 14 | { 15 | CancellationTokenSource cts = new CancellationTokenSource(); 16 | Console.CancelKeyPress += (s, ea) => 17 | { 18 | ea.Cancel = true; 19 | cts.Cancel(); 20 | }; 21 | 22 | using (MajordomoClient session = new MajordomoClient("tcp://127.0.0.1:5555", Verbose)) 23 | { 24 | int count; 25 | for (count = 0; count < 100000 && !cts.IsCancellationRequested; count++) 26 | { 27 | ZMessage request = new ZMessage(); 28 | request.Prepend(new ZFrame("Hello world")); 29 | session.Send("echo", request, cts); 30 | } 31 | for (count = 0; count < 100000 && !cts.IsCancellationRequested; count++) 32 | { 33 | using (ZMessage reply = session.Recv(cts)) 34 | if (reply == null) 35 | break; // Interrupt or failure 36 | } 37 | Console.WriteLine("{0} replies received\n", count); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ZGuideExamples/mdp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using ZeroMQ; 7 | 8 | namespace Examples 9 | { 10 | 11 | public static class MdpCommon 12 | { 13 | public const int HEARTBEAT_LIVENESS = 3; 14 | 15 | public static readonly TimeSpan HEARTBEAT_DELAY = TimeSpan.FromMilliseconds(2500); 16 | public static readonly TimeSpan RECONNECT_DELAY = TimeSpan.FromMilliseconds(2500); 17 | 18 | public static readonly TimeSpan HEARTBEAT_INTERVAL = TimeSpan.FromMilliseconds(2500); 19 | public static readonly TimeSpan HEARTBEAT_EXPIRY = 20 | TimeSpan.FromMilliseconds(HEARTBEAT_INTERVAL.TotalMilliseconds * HEARTBEAT_LIVENESS); 21 | 22 | public static readonly string MDPW_WORKER = "MDPW01"; 23 | public static readonly string MDPC_CLIENT = "MDPC01"; 24 | 25 | //public static readonly string READY = "001"; 26 | //public static readonly string REQUEST = "002"; 27 | //public static readonly string REPLY = "003"; 28 | //public static readonly string HEARTBEAT = "004"; 29 | //public static readonly string DISCONNECT = "005"; 30 | 31 | public enum MdpwCmd : byte { READY = 1, REQUEST = 2, REPLY = 3, HEARTBEAT = 4, DISCONNECT = 5 } 32 | } 33 | 34 | public static class MdpExtensions 35 | { 36 | public static bool StrHexEq(this ZFrame zfrm, MdpCommon.MdpwCmd cmd) 37 | { 38 | return zfrm.ToString().ToMdCmd().Equals(cmd); 39 | } 40 | 41 | /// 42 | /// Parse hex value to MdpwCmd, if parsing fails, return 0 43 | /// 44 | /// hex string 45 | /// MdpwCmd, return 0 if parsing failed 46 | public static MdpCommon.MdpwCmd ToMdCmd(this string hexval) 47 | { 48 | try 49 | { 50 | MdpCommon.MdpwCmd cmd = (MdpCommon.MdpwCmd)byte.Parse(hexval, NumberStyles.AllowHexSpecifier); 51 | return cmd; 52 | } 53 | catch (FormatException) 54 | { 55 | return 0; 56 | } 57 | } 58 | 59 | public static string ToHexString(this MdpCommon.MdpwCmd cmd) 60 | { 61 | return cmd.ToString("X"); 62 | } 63 | 64 | public static void DumpString(this string format, params object[] args) 65 | { 66 | // if you dont wanna see utc timeshift, remove zzz and use DateTime.UtcNow instead 67 | Console.WriteLine("[{0}] - {1}", string.Format("{0:yyyy-MM-ddTHH:mm:ss:fffffff zzz}", DateTime.Now), string.Format(format, args)); 68 | } 69 | 70 | /// 71 | /// Based on zmsg_dump 72 | /// https://github.com/imatix/zguide/blob/f94e8995a5e02d843434ace904a7afc48e266b3f/articles/src/multithreading/zmsg.c 73 | /// 74 | /// 75 | /// 76 | /// 77 | public static void DumpZmsg(this ZMessage zmsg, string format = null, params object[] args) 78 | { 79 | if (!string.IsNullOrWhiteSpace(format)) 80 | format.DumpString(args); 81 | using (var dmsg = zmsg.Duplicate()) 82 | foreach (var zfrm in dmsg) 83 | { 84 | zfrm.DumpZfrm(); 85 | } 86 | } 87 | 88 | public static void DumpZfrm(this ZFrame zfrm, string format = null, params object[] args) 89 | { 90 | if(!string.IsNullOrWhiteSpace(format)) 91 | format.DumpString(args); 92 | 93 | byte[] data = zfrm.Read(); 94 | long size = zfrm.Length; 95 | 96 | // Dump the message as text or binary 97 | bool isText = true; 98 | for (int i = 0; i < size; i++) 99 | if (data[i] < 32 || data[i] > 127) 100 | isText = false; 101 | string datastr = isText ? Encoding.UTF8.GetString(data) : data.ToHexString(); 102 | "\tD: [{0,3:D3}]:{1}".DumpString(size, datastr); 103 | } 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /ZGuideExamples/mdworker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading; 4 | using ZeroMQ; 5 | 6 | namespace Examples 7 | { 8 | using MDWrkApi; // Let us build this source without creating a library 9 | 10 | static partial class Program 11 | { 12 | // Majordomo Protocol worker example 13 | // Uses the mdwrk API to hide all MDP aspects 14 | public static void MDWorker(string[] args) 15 | { 16 | CancellationTokenSource cts = new CancellationTokenSource(); 17 | Console.CancelKeyPress += (s, ea) => 18 | { 19 | ea.Cancel = true; 20 | cts.Cancel(); 21 | }; 22 | 23 | using (MajordomoWorker session = new MajordomoWorker("tcp://127.0.0.1:5555", "echo", Verbose)) 24 | { 25 | ZMessage reply = null; 26 | while (true) 27 | { 28 | ZMessage request = session.Recv(reply, cts); 29 | if (request == null) 30 | break; // worker was interrupted 31 | reply = request; // Echo is complex 32 | } 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ZGuideExamples/mmiecho.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | // using System.Runtime.Remoting.Messaging; 6 | using System.Text; 7 | using System.Threading; 8 | using ZeroMQ; 9 | 10 | namespace Examples 11 | { 12 | // Lets us build this source without creating a library 13 | using MDCliApi; 14 | 15 | static partial class Program 16 | { 17 | // MMI echo query example 18 | public static void MMIEcho(string[] args) 19 | { 20 | CancellationTokenSource cancellor = new CancellationTokenSource(); 21 | Console.CancelKeyPress += (s, ea) => 22 | { 23 | ea.Cancel = true; 24 | cancellor.Cancel(); 25 | }; 26 | 27 | using (MajordomoClient session = new MajordomoClient("tcp://127.0.0.1:5555", Verbose)) 28 | { 29 | ZMessage request = new ZMessage(); 30 | request.Add(new ZFrame("echo")); 31 | 32 | ZMessage reply = session.Send("mmi.service", request, cancellor); 33 | if (reply != null) 34 | { 35 | var replycode = reply[0].ToString(); 36 | "Loopup echo service: {0}\n".DumpString(replycode); 37 | reply.Dispose(); 38 | } 39 | else 40 | "E: no response from broker, make sure it's running\n".DumpString(); 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ZGuideExamples/msgqueue.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void MsgQueue(string[] args) 14 | { 15 | // 16 | // Simple message queuing broker 17 | // Same as request-reply broker but using QUEUE device 18 | // 19 | // Author: metadings 20 | // 21 | 22 | // Socket facing clients and 23 | // Socket facing services 24 | using (var context = new ZContext()) 25 | using (var frontend = new ZSocket(context, ZSocketType.ROUTER)) 26 | using (var backend = new ZSocket(context, ZSocketType.DEALER)) 27 | { 28 | frontend.Bind("tcp://*:5559"); 29 | backend.Bind("tcp://*:5560"); 30 | 31 | // Start the proxy 32 | ZContext.Proxy(frontend, backend); 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /ZGuideExamples/mspoller.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void MSPoller(string[] args) 14 | { 15 | // 16 | // Reading from multiple sockets 17 | // This version uses zmq_poll() 18 | // 19 | // Author: metadings 20 | // 21 | 22 | using (var context = new ZContext()) 23 | using (var receiver = new ZSocket(context, ZSocketType.PULL)) 24 | using (var subscriber = new ZSocket(context, ZSocketType.SUB)) 25 | { 26 | // Connect to task ventilator 27 | receiver.Connect("tcp://127.0.0.1:5557"); 28 | 29 | // Connect to weather server 30 | subscriber.Connect("tcp://127.0.0.1:5556"); 31 | subscriber.SetOption(ZSocketOption.SUBSCRIBE, "10001 "); 32 | 33 | var sockets = new ZSocket[] { receiver, subscriber }; 34 | var polls = new ZPollItem[] { ZPollItem.CreateReceiver(), ZPollItem.CreateReceiver() }; 35 | 36 | // Process messages from both sockets 37 | ZError error; 38 | ZMessage[] msg; 39 | while (true) 40 | { 41 | if (sockets.PollIn(polls, out msg, out error, TimeSpan.FromMilliseconds(64))) 42 | { 43 | if (msg[0] != null) 44 | { 45 | // Process task 46 | } 47 | if (msg[1] != null) 48 | { 49 | // Process weather update 50 | } 51 | } 52 | else 53 | { 54 | if (error == ZError.ETERM) 55 | return; // Interrupted 56 | if (error != ZError.EAGAIN) 57 | throw new ZException(error); 58 | } 59 | } 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /ZGuideExamples/msreader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void MSReader(string[] args) 14 | { 15 | // 16 | // Reading from multiple sockets 17 | // This version uses a simple recv loop 18 | // 19 | // Author: metadings 20 | // 21 | 22 | using (var context = new ZContext()) 23 | using (var receiver = new ZSocket(context, ZSocketType.PULL)) 24 | using (var subscriber = new ZSocket(context, ZSocketType.SUB)) 25 | { 26 | // Connect to task ventilator 27 | receiver.Connect("tcp://127.0.0.1:5557"); 28 | 29 | // Connect to weather server 30 | subscriber.Connect("tcp://127.0.0.1:5556"); 31 | subscriber.SetOption(ZSocketOption.SUBSCRIBE, "10001 "); 32 | 33 | // Process messages from both sockets 34 | // We prioritize traffic from the task ventilator 35 | ZError error; 36 | ZFrame frame; 37 | while (true) 38 | { 39 | while (true) 40 | { 41 | if (null != (frame = receiver.ReceiveFrame(ZSocketFlags.DontWait, out error))) 42 | { 43 | // Process task 44 | } 45 | else 46 | { 47 | if (error == ZError.ETERM) 48 | return; // Interrupted 49 | if (error != ZError.EAGAIN) 50 | throw new ZException(error); 51 | 52 | break; 53 | } 54 | } 55 | 56 | while (true) 57 | { 58 | if (null != (frame = subscriber.ReceiveFrame(ZSocketFlags.DontWait, out error))) 59 | { 60 | // Process weather update 61 | } 62 | else 63 | { 64 | if (error == ZError.ETERM) 65 | return; // Interrupted 66 | if (error != ZError.EAGAIN) 67 | throw new ZException(error); 68 | 69 | break; 70 | } 71 | } 72 | 73 | // No activity, so sleep for 1 msec 74 | Thread.Sleep(1); 75 | } 76 | } 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /ZGuideExamples/mtrelay.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void MTRelay(string[] args) 14 | { 15 | // 16 | // Multithreaded relay 17 | // 18 | // Author: metadings 19 | // 20 | 21 | // Bind inproc socket before starting step2 22 | using (var ctx = new ZContext()) 23 | using (var receiver = new ZSocket(ctx, ZSocketType.PAIR)) 24 | { 25 | receiver.Bind("inproc://step3"); 26 | 27 | new Thread(() => MTRelay_step2(ctx)).Start(); 28 | 29 | // Wait for signal 30 | receiver.ReceiveFrame(); 31 | 32 | Console.WriteLine("Test successful!"); 33 | } 34 | } 35 | 36 | static void MTRelay_step2(ZContext ctx) 37 | { 38 | // Bind inproc socket before starting step1 39 | using (var receiver = new ZSocket(ctx, ZSocketType.PAIR)) 40 | { 41 | receiver.Bind("inproc://step2"); 42 | 43 | new Thread(() => MTRelay_step1(ctx)).Start(); 44 | 45 | // Wait for signal and pass it on 46 | receiver.ReceiveFrame(); 47 | } 48 | 49 | // Connect to step3 and tell it we're ready 50 | using (var xmitter = new ZSocket(ctx, ZSocketType.PAIR)) 51 | { 52 | xmitter.Connect("inproc://step3"); 53 | 54 | Console.WriteLine("Step 2 ready, signaling step 3"); 55 | xmitter.Send(new ZFrame("READY")); 56 | } 57 | } 58 | 59 | static void MTRelay_step1(ZContext ctx) 60 | { 61 | // Connect to step2 and tell it we're ready 62 | using (var xmitter = new ZSocket(ctx, ZSocketType.PAIR)) 63 | { 64 | xmitter.Connect("inproc://step2"); 65 | 66 | Console.WriteLine("Step 1 ready, signaling step 2"); 67 | xmitter.Send(new ZFrame("READY")); 68 | } 69 | } 70 | 71 | } 72 | } -------------------------------------------------------------------------------- /ZGuideExamples/mtserver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void MTServer(string[] args) 14 | { 15 | // 16 | // Multithreaded Hello World server 17 | // 18 | // Author: metadings 19 | // 20 | 21 | // Socket to talk to clients and 22 | // Socket to talk to workers 23 | using (var ctx = new ZContext()) 24 | using (var clients = new ZSocket(ctx, ZSocketType.ROUTER)) 25 | using (var workers = new ZSocket(ctx, ZSocketType.DEALER)) 26 | { 27 | clients.Bind("tcp://*:5555"); 28 | workers.Bind("inproc://workers"); 29 | 30 | // Launch pool of worker threads 31 | for (int i = 0; i < 5; ++i) 32 | { 33 | new Thread(() => MTServer_Worker(ctx)).Start(); 34 | } 35 | 36 | // Connect work threads to client threads via a queue proxy 37 | ZContext.Proxy(clients, workers); 38 | } 39 | } 40 | 41 | static void MTServer_Worker(ZContext ctx) 42 | { 43 | // Socket to talk to dispatcher 44 | using (var server = new ZSocket(ctx, ZSocketType.REP)) 45 | { 46 | server.Connect("inproc://workers"); 47 | 48 | while (true) 49 | { 50 | using (ZFrame frame = server.ReceiveFrame()) 51 | { 52 | Console.Write("Received: {0}", frame.ReadString()); 53 | 54 | // Do some 'work' 55 | Thread.Sleep(1); 56 | 57 | // Send reply back to client 58 | string replyText = "World"; 59 | Console.WriteLine(", Sending: {0}", replyText); 60 | server.Send(new ZFrame(replyText)); 61 | } 62 | } 63 | } 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /ZGuideExamples/pathopub.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void PathoPub(string[] args) 14 | { 15 | // 16 | // Pathological publisher 17 | // Sends out 1,000 topics and then one random update per second 18 | // 19 | // Author: metadings 20 | // 21 | 22 | if (args == null || args.Length < 1) 23 | { 24 | Console.WriteLine(); 25 | Console.WriteLine("Usage: ./{0} PathoPub [Endpoint]", AppDomain.CurrentDomain.FriendlyName); 26 | Console.WriteLine(); 27 | Console.WriteLine(" Endpoint Where PathoPub should connect to."); 28 | Console.WriteLine(" Default is null, Binding on tcp://*:5556"); 29 | Console.WriteLine(); 30 | args = new string[] { null }; 31 | } 32 | 33 | using (var context = new ZContext()) 34 | using (var publisher = new ZSocket(context, ZSocketType.PUB)) 35 | { 36 | if (args[0] != null) 37 | { 38 | publisher.Connect(args[0]); 39 | } 40 | else 41 | { 42 | publisher.Bind("tcp://*:5556"); 43 | } 44 | 45 | // Ensure subscriber connection has time to complete 46 | Thread.Sleep(100); 47 | 48 | // Send out all 1,000 topic messages 49 | for (int topic = 0; topic < 1000; ++topic) 50 | { 51 | publisher.SendMore(new ZFrame(string.Format("{0:D3}", topic))); 52 | publisher.Send(new ZFrame("Save Roger")); 53 | } 54 | 55 | // Send one random update per second 56 | var rnd = new Random(); 57 | while (true) 58 | { 59 | Thread.Sleep(10); 60 | publisher.SendMore(new ZFrame(string.Format("{0:D3}", rnd.Next(1000)))); 61 | publisher.Send(new ZFrame("Off with his head!")); 62 | } 63 | } 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /ZGuideExamples/pathosub.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void PathoSub(string[] args) 14 | { 15 | // 16 | // Pathological subscriber 17 | // Subscribes to one random topic and prints received messages 18 | // 19 | // Author: metadings 20 | // 21 | 22 | if (args == null || args.Length < 1) 23 | { 24 | Console.WriteLine(); 25 | Console.WriteLine("Usage: ./{0} PathoSub [Endpoint]", AppDomain.CurrentDomain.FriendlyName); 26 | Console.WriteLine(); 27 | Console.WriteLine(" Endpoint Where PathoSub should connect to."); 28 | Console.WriteLine(" Default is tcp://127.0.0.1:5556"); 29 | Console.WriteLine(); 30 | args = new string[] { "tcp://127.0.0.1:5556" }; 31 | } 32 | 33 | using (var context = new ZContext()) 34 | using (var subscriber = new ZSocket(context, ZSocketType.SUB)) 35 | { 36 | subscriber.Connect(args[0]); 37 | 38 | var rnd = new Random(); 39 | var subscription = string.Format("{0:D3}", rnd.Next(1000)); 40 | subscriber.Subscribe(subscription); 41 | 42 | ZMessage msg; 43 | ZError error; 44 | while (true) 45 | { 46 | if (null == (msg = subscriber.ReceiveMessage(out error))) 47 | { 48 | if (error == ZError.ETERM) 49 | break; // Interrupted 50 | throw new ZException(error); 51 | } 52 | using (msg) 53 | { 54 | if (msg[0].ReadString() != subscription) 55 | { 56 | throw new InvalidOperationException(); 57 | } 58 | Console.WriteLine(msg[1].ReadString()); 59 | } 60 | } 61 | } 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /ZGuideExamples/peering1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | // 14 | // Broker peering simulation (part 1) 15 | // Prototypes the state flow 16 | // 17 | // Author: metadings 18 | // 19 | 20 | public static void Peering1(string[] args) 21 | { 22 | // First argument is this broker's name 23 | // Other arguments are our peers' names 24 | // 25 | if (args == null || args.Length < 2) 26 | { 27 | Console.WriteLine(); 28 | Console.WriteLine("Usage: {0} Peering1 World Receiver0", AppDomain.CurrentDomain.FriendlyName); 29 | Console.WriteLine(" {0} Peering1 Receiver0 World", AppDomain.CurrentDomain.FriendlyName); 30 | Console.WriteLine(); 31 | return; 32 | } 33 | string self = args[0]; 34 | Console.WriteLine("I: preparing broker as {0}", self); 35 | 36 | using (var context = new ZContext()) 37 | using (var backend = new ZSocket(context, ZSocketType.PUB)) 38 | using (var frontend = new ZSocket(context, ZSocketType.SUB)) 39 | { 40 | // Bind backend to endpoint 41 | backend.Bind("tcp://127.0.0.1:" + Peering1_GetPort(self)); 42 | 43 | // Connect frontend to all peers 44 | frontend.SubscribeAll(); 45 | for (int i = 1; i < args.Length; ++i) 46 | { 47 | string peer = args[i]; 48 | Console.WriteLine("I: connecting to state backend at {0}", peer); 49 | frontend.Connect("tcp://127.0.0.1:" + Peering1_GetPort(peer)); 50 | } 51 | 52 | // The main loop sends out status messages to peers, and collects 53 | // status messages back from peers. The zmq_poll timeout defines 54 | // our own heartbeat: 55 | 56 | ZError error; 57 | ZMessage incoming; 58 | var poll = ZPollItem.CreateReceiver(); 59 | var rnd = new Random(); 60 | 61 | while (true) 62 | { 63 | // Poll for activity, or 1 second timeout 64 | if (!frontend.PollIn(poll, out incoming, out error, TimeSpan.FromSeconds(1))) 65 | { 66 | if (error == ZError.EAGAIN) 67 | { 68 | using (var output = new ZMessage()) 69 | { 70 | output.Add(new ZFrame(self)); 71 | 72 | var outputNumber = ZFrame.Create(4); 73 | outputNumber.Write(rnd.Next(10)); 74 | output.Add(outputNumber); 75 | 76 | backend.Send(output); 77 | } 78 | 79 | continue; 80 | } 81 | if (error == ZError.ETERM) 82 | return; 83 | 84 | throw new ZException(error); 85 | } 86 | using (incoming) 87 | { 88 | string peer_name = incoming[0].ReadString(); 89 | int available = incoming[1].ReadInt32(); 90 | Console.WriteLine("{0} - {1} workers free", peer_name, available); 91 | } 92 | } 93 | } 94 | } 95 | 96 | static Int16 Peering1_GetPort(string name) 97 | { 98 | var hash = (Int16)name[0]; 99 | if (hash < 1024) 100 | { 101 | hash += 1024; 102 | } 103 | return hash; 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /ZGuideExamples/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | "description": "ZeroMQ/clrzmq4/ZGuideExamples", 4 | 5 | "dependencies": { }, 6 | "runtimes": { 7 | "win": { } 8 | }, 9 | "frameworks": { 10 | ".NETFramework,Version=v4.0": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ZGuideExamples/psenvpub.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void PSEnvPub(string[] args) 14 | { 15 | // 16 | // Pubsub envelope publisher 17 | // 18 | // Author: metadings 19 | // 20 | 21 | // Prepare our context and publisher 22 | using (var context = new ZContext()) 23 | using (var publisher = new ZSocket(context, ZSocketType.PUB)) 24 | { 25 | publisher.Linger = TimeSpan.Zero; 26 | publisher.Bind("tcp://*:5563"); 27 | 28 | int published = 0; 29 | while (true) 30 | { 31 | // Write two messages, each with an envelope and content 32 | 33 | using (var message = new ZMessage()) 34 | { 35 | published++; 36 | message.Add(new ZFrame(string.Format("A {0}", published))); 37 | message.Add(new ZFrame(string.Format(" We don't like to see this."))); 38 | Thread.Sleep(1000); 39 | 40 | Console_WriteZMessage("Publishing ", message); 41 | publisher.Send(message); 42 | } 43 | 44 | using (var message = new ZMessage()) 45 | { 46 | published++; 47 | message.Add(new ZFrame(string.Format("B {0}", published))); 48 | message.Add(new ZFrame(string.Format(" We do like to see this."))); 49 | Thread.Sleep(1000); 50 | 51 | Console_WriteZMessage("Publishing ", message); 52 | publisher.Send(message); 53 | } 54 | } 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /ZGuideExamples/psenvsub.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void PSEnvSub(string[] args) 14 | { 15 | // 16 | // Pubsub envelope subscriber 17 | // 18 | // Author: metadings 19 | // 20 | 21 | // Prepare our context and subscriber 22 | using (var context = new ZContext()) 23 | using (var subscriber = new ZSocket(context, ZSocketType.SUB)) 24 | { 25 | subscriber.Connect("tcp://127.0.0.1:5563"); 26 | subscriber.Subscribe("B"); 27 | 28 | int subscribed = 0; 29 | while (true) 30 | { 31 | using (ZMessage message = subscriber.ReceiveMessage()) 32 | { 33 | subscribed++; 34 | 35 | // Read envelope with address 36 | string address = message[0].ReadString(); 37 | 38 | // Read message contents 39 | string contents = message[1].ReadString(); 40 | 41 | Console.WriteLine("{0}. [{1}] {2}", subscribed, address, contents); 42 | } 43 | } 44 | } 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /ZGuideExamples/rrbroker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void RRBroker(string[] args) 14 | { 15 | // 16 | // Simple request-reply broker 17 | // 18 | // Author: metadings 19 | // 20 | 21 | // Prepare our context and sockets 22 | using (var ctx = new ZContext()) 23 | using (var frontend = new ZSocket(ctx, ZSocketType.ROUTER)) 24 | using (var backend = new ZSocket(ctx, ZSocketType.DEALER)) 25 | { 26 | frontend.Bind("tcp://*:5559"); 27 | backend.Bind("tcp://*:5560"); 28 | 29 | // Initialize poll set 30 | var poll = ZPollItem.CreateReceiver(); 31 | 32 | // Switch messages between sockets 33 | ZError error; 34 | ZMessage message; 35 | while (true) 36 | { 37 | if (frontend.PollIn(poll, out message, out error, TimeSpan.FromMilliseconds(64))) 38 | { 39 | // Process all parts of the message 40 | Console_WriteZMessage("frontend", 2, message); 41 | backend.Send(message); 42 | } 43 | else 44 | { 45 | if (error == ZError.ETERM) 46 | return; // Interrupted 47 | if (error != ZError.EAGAIN) 48 | throw new ZException(error); 49 | } 50 | 51 | if (backend.PollIn(poll, out message, out error, TimeSpan.FromMilliseconds(64))) 52 | { 53 | // Process all parts of the message 54 | Console_WriteZMessage(" backend", 2, message); 55 | frontend.Send(message); 56 | } 57 | else 58 | { 59 | if (error == ZError.ETERM) 60 | return; // Interrupted 61 | if (error != ZError.EAGAIN) 62 | throw new ZException(error); 63 | } 64 | } 65 | } 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /ZGuideExamples/rrclient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void RRClient(string[] args) 14 | { 15 | // 16 | // Hello World client 17 | // Connects REQ socket to tcp://127.0.0.1:5559 18 | // Sends "Hello" to server, expects "World" back 19 | // 20 | // Author: metadings 21 | // 22 | 23 | // Socket to talk to server 24 | using (var context = new ZContext()) 25 | using (var requester = new ZSocket(context, ZSocketType.REQ)) 26 | { 27 | requester.Connect("tcp://127.0.0.1:5559"); 28 | 29 | for (int n = 0; n < 10; ++n) 30 | { 31 | requester.Send(new ZFrame("Hello")); 32 | 33 | using (ZFrame reply = requester.ReceiveFrame()) 34 | { 35 | Console.WriteLine("Hello {0}!", reply.ReadString()); 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /ZGuideExamples/rrworker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void RRWorker(string[] args) 14 | { 15 | // 16 | // Hello World worker 17 | // Connects REP socket to tcp://127.0.0.1:5560 18 | // Expects "Hello" from client, replies with "World" 19 | // 20 | // Author: metadings 21 | // 22 | 23 | if (args == null || args.Length < 2) 24 | { 25 | Console.WriteLine(); 26 | Console.WriteLine("Usage: ./{0} RRWorker [Name] [Endpoint]", AppDomain.CurrentDomain.FriendlyName); 27 | Console.WriteLine(); 28 | Console.WriteLine(" Name Your Name"); 29 | Console.WriteLine(" Endpoint Where RRWorker should connect to."); 30 | Console.WriteLine(" Default is tcp://127.0.0.1:5560"); 31 | Console.WriteLine(); 32 | if (args.Length < 1) { 33 | args = new string[] { "World", "tcp://127.0.0.1:5560" }; 34 | } else { 35 | args = new string[] { args[0], "tcp://127.0.0.1:5560" }; 36 | } 37 | } 38 | 39 | string name = args[0]; 40 | 41 | string endpoint = args[1]; 42 | 43 | // Socket to talk to clients 44 | using (var context = new ZContext()) 45 | using (var responder = new ZSocket(context, ZSocketType.REP)) 46 | { 47 | responder.Connect(endpoint); 48 | 49 | while (true) 50 | { 51 | // Wait for next request from client 52 | using (ZFrame request = responder.ReceiveFrame()) 53 | { 54 | Console.Write("{0} ", request.ReadString()); 55 | 56 | // Do some 'work' 57 | Thread.Sleep(1); 58 | 59 | // Send reply back to client 60 | Console.WriteLine("{0}... ", name); 61 | responder.Send(new ZFrame(name)); 62 | } 63 | } 64 | } 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /ZGuideExamples/rtdealer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading; 7 | 8 | using ZeroMQ; 9 | 10 | namespace Examples 11 | { 12 | static partial class Program 13 | { 14 | static int RTDealer_Workers = 10; 15 | 16 | public static void RTDealer(string[] args) 17 | { 18 | // 19 | // ROUTER-to-DEALER example 20 | // 21 | // While this example runs in a single process, that is only to make 22 | // it easier to start and stop the example. Each thread has its own 23 | // context and conceptually acts as a separate process. 24 | // 25 | // Author: metadings 26 | // 27 | 28 | using (var context = new ZContext()) 29 | using (var broker = new ZSocket(context, ZSocketType.ROUTER)) 30 | { 31 | broker.Bind("tcp://*:5671"); 32 | 33 | for (int i = 0; i < RTDealer_Workers; ++i) 34 | { 35 | int j = i; new Thread(() => RTDealer_Worker(j)).Start(); 36 | } 37 | 38 | var stopwatch = new Stopwatch(); 39 | stopwatch.Start(); 40 | 41 | // Run for five seconds and then tell workers to end 42 | int workers_fired = 0; 43 | while (true) 44 | { 45 | // Next message gives us least recently used worker 46 | using (ZMessage identity = broker.ReceiveMessage()) 47 | { 48 | broker.SendMore(identity[0]); 49 | broker.SendMore(new ZFrame()); 50 | 51 | // Encourage workers until it's time to fire them 52 | if (stopwatch.Elapsed < TimeSpan.FromSeconds(5)) 53 | { 54 | broker.Send(new ZFrame("Work harder!")); 55 | } 56 | else 57 | { 58 | broker.Send(new ZFrame("Fired!")); 59 | 60 | if (++workers_fired == RTDealer_Workers) 61 | { 62 | break; 63 | } 64 | } 65 | } 66 | } 67 | } 68 | } 69 | 70 | static void RTDealer_Worker(int i) 71 | { 72 | using (var context = new ZContext()) 73 | using (var worker = new ZSocket(context, ZSocketType.DEALER)) 74 | { 75 | worker.IdentityString = "PEER" + i; // Set a printable identity 76 | worker.Connect("tcp://127.0.0.1:5671"); 77 | 78 | int total = 0; 79 | while (true) 80 | { 81 | // Tell the broker we're ready for work 82 | worker.SendMore(new ZFrame(worker.Identity)); 83 | worker.SendMore(new ZFrame()); 84 | worker.Send(new ZFrame("Hi Boss")); 85 | 86 | // Get workload from broker, until finished 87 | using (ZMessage msg = worker.ReceiveMessage()) 88 | { 89 | bool finished = (msg[1].ReadString() == "Fired!"); 90 | 91 | if (finished) 92 | { 93 | break; 94 | } 95 | } 96 | 97 | total++; 98 | 99 | // Do some random work 100 | Thread.Sleep(1); 101 | } 102 | 103 | Console.WriteLine("Completed: PEER{0}, {1} tasks", i, total); 104 | } 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /ZGuideExamples/rtreq.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading; 7 | 8 | using ZeroMQ; 9 | 10 | namespace Examples 11 | { 12 | static partial class Program 13 | { 14 | static int RTReq_Workers = 10; 15 | 16 | public static void RTReq(string[] args) 17 | { 18 | // 19 | // ROUTER-to-REQ example 20 | // 21 | // While this example runs in a single process, that is only to make 22 | // it easier to start and stop the example. Each thread has its own 23 | // context and conceptually acts as a separate process. 24 | // 25 | // Author: metadings 26 | // 27 | 28 | using (var context = new ZContext()) 29 | using (var broker = new ZSocket(context, ZSocketType.ROUTER)) 30 | { 31 | broker.Bind("tcp://*:5671"); 32 | 33 | for (int i = 0; i < RTReq_Workers; ++i) 34 | { 35 | int j = i; new Thread(() => RTReq_Worker(j)).Start(); 36 | } 37 | 38 | var stopwatch = new Stopwatch(); 39 | stopwatch.Start(); 40 | 41 | // Run for five seconds and then tell workers to end 42 | int workers_fired = 0; 43 | while (true) 44 | { 45 | // Next message gives us least recently used worker 46 | using (ZMessage identity = broker.ReceiveMessage()) 47 | { 48 | broker.SendMore(identity[0]); 49 | broker.SendMore(new ZFrame()); 50 | 51 | // Encourage workers until it's time to fire them 52 | if (stopwatch.Elapsed < TimeSpan.FromSeconds(5)) 53 | { 54 | broker.Send(new ZFrame("Work harder!")); 55 | } 56 | else 57 | { 58 | broker.Send(new ZFrame("Fired!")); 59 | 60 | if (++workers_fired == RTReq_Workers) 61 | { 62 | break; 63 | } 64 | } 65 | } 66 | } 67 | } 68 | } 69 | 70 | static void RTReq_Worker(int i) 71 | { 72 | using (var context = new ZContext()) 73 | using (var worker = new ZSocket(context, ZSocketType.REQ)) 74 | { 75 | worker.IdentityString = "PEER" + i; // Set a printable identity 76 | worker.Connect("tcp://127.0.0.1:5671"); 77 | 78 | int total = 0; 79 | while (true) 80 | { 81 | // Tell the broker we're ready for work 82 | worker.Send(new ZFrame("Hi Boss")); 83 | 84 | // Get workload from broker, until finished 85 | using (ZFrame frame = worker.ReceiveFrame()) 86 | { 87 | bool finished = (frame.ReadString() == "Fired!"); 88 | if (finished) 89 | { 90 | break; 91 | } 92 | } 93 | 94 | total++; 95 | 96 | // Do some random work 97 | Thread.Sleep(1); 98 | } 99 | 100 | Console.WriteLine("Completed: PEER{0}, {1} tasks", i, total); 101 | } 102 | } 103 | } 104 | } -------------------------------------------------------------------------------- /ZGuideExamples/spqueue.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void SPQueue(string[] args) 14 | { 15 | // 16 | // Simple Pirate broker 17 | // This is identical to load-balancing pattern, with no reliability 18 | // mechanisms. It depends on the client for recovery. Runs forever. 19 | // 20 | // Author: metadings 21 | // 22 | 23 | using (var context = new ZContext()) 24 | using (var frontend = new ZSocket(context, ZSocketType.ROUTER)) 25 | using (var backend = new ZSocket(context, ZSocketType.ROUTER)) 26 | { 27 | frontend.Bind("tcp://*:5555"); 28 | backend.Bind("tcp://*:5556"); 29 | 30 | // Queue of available workers 31 | var worker_queue = new List(); 32 | 33 | ZError error; 34 | ZMessage incoming; 35 | var poll = ZPollItem.CreateReceiver(); 36 | 37 | while (true) 38 | { 39 | if (backend.PollIn(poll, out incoming, out error, TimeSpan.FromMilliseconds(64))) 40 | { 41 | using (incoming) 42 | { 43 | // Handle worker activity on backend 44 | 45 | // incoming[0] is worker_id 46 | string worker_id = incoming[0].ReadString(); 47 | // Queue worker identity for load-balancing 48 | worker_queue.Add(worker_id); 49 | 50 | // incoming[1] is empty 51 | 52 | // incoming[2] is READY or else client_id 53 | string client_id = incoming[2].ReadString(); 54 | 55 | if (client_id == "READY") 56 | { 57 | Console.WriteLine("I: ({0}) worker ready", worker_id); 58 | } 59 | else 60 | { 61 | // incoming[3] is empty 62 | 63 | // incoming[4] is reply 64 | // string reply = incoming[4].ReadString(); 65 | // int reply = incoming[4].ReadInt32(); 66 | 67 | Console.WriteLine("I: ({0}) work complete", worker_id); 68 | 69 | using (var outgoing = new ZMessage()) 70 | { 71 | outgoing.Add(new ZFrame(client_id)); 72 | outgoing.Add(new ZFrame()); 73 | outgoing.Add(incoming[4]); 74 | 75 | // Send 76 | frontend.Send(outgoing); 77 | } 78 | } 79 | } 80 | } 81 | else 82 | { 83 | if (error == ZError.ETERM) 84 | return; 85 | if (error != ZError.EAGAIN) 86 | throw new ZException(error); 87 | } 88 | 89 | if (worker_queue.Count > 0) 90 | { 91 | // Poll frontend only if we have available workers 92 | 93 | if (frontend.PollIn(poll, out incoming, out error, TimeSpan.FromMilliseconds(64))) 94 | { 95 | using (incoming) 96 | { 97 | // Here is how we handle a client request 98 | 99 | // Dequeue the next worker identity 100 | string worker_id = worker_queue[0]; 101 | worker_queue.RemoveAt(0); 102 | 103 | // incoming[0] is client_id 104 | string client_id = incoming[0].ReadString(); 105 | 106 | // incoming[1] is empty 107 | 108 | // incoming[2] is request 109 | // string request = incoming[2].ReadString(); 110 | int request = incoming[2].ReadInt32(); 111 | 112 | Console.WriteLine("I: ({0}) working on ({1}) {2}", worker_id, client_id, request); 113 | 114 | using (var outgoing = new ZMessage()) 115 | { 116 | outgoing.Add(new ZFrame(worker_id)); 117 | outgoing.Add(new ZFrame()); 118 | outgoing.Add(new ZFrame(client_id)); 119 | outgoing.Add(new ZFrame()); 120 | outgoing.Add(incoming[2]); 121 | 122 | // Send 123 | backend.Send(outgoing); 124 | } 125 | } 126 | } 127 | else 128 | { 129 | if (error == ZError.ETERM) 130 | return; 131 | if (error != ZError.EAGAIN) 132 | throw new ZException(error); 133 | } 134 | } 135 | } 136 | } 137 | } 138 | } 139 | } -------------------------------------------------------------------------------- /ZGuideExamples/spworker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void SPWorker(string[] args) 14 | { 15 | // 16 | // Simple Pirate worker 17 | // Connects REQ socket to tcp://127.0.0.1:5556 18 | // Implements worker part of load-balancing 19 | // 20 | // Author: metadings 21 | // 22 | 23 | var rnd = new Random(); 24 | if (args == null || args.Length < 1) 25 | { 26 | args = new string[] { "World" + rnd.Next() }; 27 | } 28 | string name = args[0]; 29 | 30 | using (var context = new ZContext()) 31 | using (var worker = new ZSocket(context, ZSocketType.REQ)) 32 | { 33 | worker.Identity = Encoding.UTF8.GetBytes(name); 34 | worker.Connect("tcp://127.0.0.1:5556"); 35 | 36 | Console.WriteLine("I: ({0}) worker ready", name); 37 | 38 | using (var outgoing = new ZFrame("READY")) 39 | { 40 | worker.Send(outgoing); 41 | } 42 | 43 | int cycles = 0; 44 | ZError error; 45 | ZMessage incoming; 46 | 47 | while (true) 48 | { 49 | if (null == (incoming = worker.ReceiveMessage(out error))) 50 | { 51 | if (error == ZError.ETERM) 52 | return; 53 | 54 | throw new ZException(error); 55 | } 56 | using (incoming) 57 | { 58 | // Simulate various problems, after a few cycles 59 | cycles++; 60 | 61 | if (cycles > 3 && rnd.Next(5) == 0) 62 | { 63 | Console.WriteLine("I: ({0}) simulating a crash", name); 64 | return; 65 | } 66 | else if (cycles > 3 && rnd.Next(5) == 0) 67 | { 68 | Console.WriteLine("I: ({0}) simulating CPU overload", name); 69 | Thread.Sleep(500); 70 | } 71 | 72 | Console.WriteLine("I: ({0}) normal reply", name); 73 | 74 | Thread.Sleep(1); // Do some heavy work 75 | 76 | // Send message back 77 | worker.Send(incoming); 78 | } 79 | } 80 | 81 | } 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /ZGuideExamples/suisnail.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | // 14 | // Suicidal Snail 15 | // 16 | // Author: metadings 17 | // 18 | 19 | static readonly TimeSpan SuiSnail_MAX_ALLOWED_DELAY = TimeSpan.FromMilliseconds(1000); 20 | 21 | static void SuiSnail_Subscriber(ZContext context, ZSocket backend, CancellationTokenSource cancellor, object[] args) 22 | { 23 | // This is our subscriber. It connects to the publisher and subscribes 24 | // to everything. It sleeps for a short time between messages to 25 | // simulate doing too much work. If a message is more than one second 26 | // late, it croaks. 27 | 28 | using (var subscriber = new ZSocket(context, ZSocketType.SUB)) 29 | { 30 | // Subscribe to everything 31 | subscriber.SubscribeAll(); 32 | subscriber.Connect("tcp://127.0.0.1:5556"); 33 | 34 | ZFrame incoming; 35 | ZError error; 36 | var rnd = new Random(); 37 | while (!cancellor.IsCancellationRequested) 38 | { 39 | // Get and process messages 40 | if (null != (incoming = subscriber.ReceiveFrame(out error))) 41 | { 42 | string terms = incoming.ReadString(); 43 | Console.WriteLine(terms); 44 | var clock = DateTime.Parse(terms); 45 | 46 | // Suicide snail logic 47 | if (DateTime.UtcNow - clock > SuiSnail_MAX_ALLOWED_DELAY) 48 | { 49 | Console.WriteLine("E: subscriber cannot keep up, aborting"); 50 | break; 51 | } 52 | 53 | // Work for 1 msec plus some random additional time 54 | Thread.Sleep(1 + rnd.Next(200)); 55 | } 56 | else 57 | { 58 | if (error == ZError.ETERM) 59 | break; // Interrupted 60 | throw new ZException(error); 61 | } 62 | } 63 | 64 | backend.Send(new ZFrame("gone and died")); 65 | } 66 | } 67 | 68 | static void SuiSnail_Publisher(ZContext context, ZSocket backend, CancellationTokenSource cancellor, object[] args) 69 | { 70 | // This is our publisher task. It publishes a time-stamped message to its 71 | // PUB socket every millisecond: 72 | 73 | using (var publisher = new ZSocket(context, ZSocketType.PUB)) 74 | { 75 | // Prepare publisher 76 | publisher.Bind("tcp://*:5556"); 77 | 78 | ZFrame signal; 79 | ZError error; 80 | while (!cancellor.IsCancellationRequested) 81 | { 82 | // Send current clock (msecs) to subscribers 83 | if (!publisher.Send(new ZFrame(DateTime.UtcNow.ToString("s")), out error)) 84 | { 85 | if (error == ZError.ETERM) 86 | break; // Interrupted 87 | throw new ZException(error); 88 | } 89 | 90 | if (null == (signal = backend.ReceiveFrame(ZSocketFlags.DontWait, out error))) 91 | { 92 | if (error == ZError.EAGAIN) 93 | { 94 | Thread.Sleep(1); // wait 1 ms 95 | continue; 96 | } 97 | if (error == ZError.ETERM) 98 | break; // Interrupted 99 | throw new ZException(error); 100 | } 101 | 102 | // Suicide snail logic 103 | using (signal) break; 104 | } 105 | } 106 | } 107 | 108 | public static void SuiSnail(string[] args) 109 | { 110 | // The main task simply starts a client and a server, and then 111 | // waits for the client to signal that it has died: 112 | 113 | using (var context = new ZContext()) 114 | using (var pubpipe = new ZActor(context, SuiSnail_Publisher)) 115 | using (var subpipe = new ZActor(context, SuiSnail_Subscriber)) 116 | { 117 | pubpipe.Start(); 118 | subpipe.Start(); 119 | 120 | subpipe.Frontend.ReceiveFrame(); 121 | pubpipe.Frontend.Send(new ZFrame("break")); 122 | 123 | // wait for the Thread (you'll see how fast it is) 124 | pubpipe.Join(5000); 125 | } 126 | } 127 | } 128 | } -------------------------------------------------------------------------------- /ZGuideExamples/syncpub.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | const int SyncPub_SubscribersExpected = 3; // We wait for 3 subscribers 14 | 15 | public static void SyncPub(string[] args) 16 | { 17 | // 18 | // Synchronized publisher 19 | // 20 | // Author: metadings 21 | // 22 | 23 | // Socket to talk to clients and 24 | // Socket to receive signals 25 | using (var context = new ZContext()) 26 | using (var publisher = new ZSocket(context, ZSocketType.PUB)) 27 | using (var syncservice = new ZSocket(context, ZSocketType.REP)) 28 | { 29 | publisher.SendHighWatermark = 1100000; 30 | publisher.Bind("tcp://*:5561"); 31 | 32 | syncservice.Bind("tcp://*:5562"); 33 | 34 | // Get synchronization from subscribers 35 | int subscribers = SyncPub_SubscribersExpected; 36 | do 37 | { 38 | Console.WriteLine("Waiting for {0} subscriber" + (subscribers > 1 ? "s" : string.Empty) + "...", subscribers); 39 | 40 | // - wait for synchronization request 41 | syncservice.ReceiveFrame(); 42 | 43 | // - send synchronization reply 44 | syncservice.Send(new ZFrame()); 45 | } 46 | while (--subscribers > 0); 47 | 48 | // Now broadcast exactly 20 updates followed by END 49 | Console.WriteLine("Broadcasting messages:"); 50 | for (int i = 0; i < 20; ++i) 51 | { 52 | Console.WriteLine("Sending {0}...", i); 53 | publisher.Send(new ZFrame(i)); 54 | } 55 | publisher.Send(new ZFrame("END")); 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /ZGuideExamples/syncsub.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void SyncSub(string[] args) 14 | { 15 | // 16 | // Synchronized subscriber 17 | // 18 | // Author: metadings 19 | // 20 | 21 | using (var context = new ZContext()) 22 | using (var subscriber = new ZSocket(context, ZSocketType.SUB)) 23 | using (var syncclient = new ZSocket(context, ZSocketType.REQ)) 24 | { 25 | // First, connect our subscriber socket 26 | subscriber.Connect("tcp://127.0.0.1:5561"); 27 | subscriber.SubscribeAll(); 28 | 29 | // 0MQ is so fast, we need to wait a while… 30 | Thread.Sleep(1); 31 | 32 | // Second, synchronize with publisher 33 | syncclient.Connect("tcp://127.0.0.1:5562"); 34 | 35 | // - send a synchronization request 36 | syncclient.Send(new ZFrame()); 37 | 38 | // - wait for synchronization reply 39 | syncclient.ReceiveFrame(); 40 | 41 | // Third, get our updates and report how many we got 42 | int i = 0; 43 | while (true) 44 | { 45 | using (ZFrame frame = subscriber.ReceiveFrame()) 46 | { 47 | string text = frame.ReadString(); 48 | if (text == "END") 49 | { 50 | break; 51 | } 52 | 53 | frame.Position = 0; 54 | Console.WriteLine("Receiving {0}...", frame.ReadInt32()); 55 | 56 | ++i; 57 | } 58 | } 59 | Console.WriteLine("Received {0} updates.", i); 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /ZGuideExamples/tasksink.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading; 7 | 8 | using ZeroMQ; 9 | 10 | namespace Examples 11 | { 12 | static partial class Program 13 | { 14 | public static void TaskSink(string[] args) 15 | { 16 | // 17 | // Task sink 18 | // Binds PULL socket to tcp://127.0.0.1:5558 19 | // Collects results from workers via that socket 20 | // 21 | // Author: metadings 22 | // 23 | 24 | // Prepare our context and socket 25 | using (var context = new ZContext()) 26 | using (var sink = new ZSocket(context, ZSocketType.PULL)) 27 | { 28 | sink.Bind("tcp://*:5558"); 29 | 30 | // Wait for start of batch 31 | sink.ReceiveFrame(); 32 | 33 | // Start our clock now 34 | var stopwatch = new Stopwatch(); 35 | stopwatch.Start(); 36 | 37 | // Process 100 confirmations 38 | for (int i = 0; i < 100; ++i) 39 | { 40 | sink.ReceiveFrame(); 41 | 42 | if ((i / 10) * 10 == i) 43 | Console.Write(":"); 44 | else 45 | Console.Write("."); 46 | } 47 | 48 | // Calculate and report duration of batch 49 | stopwatch.Stop(); 50 | Console.WriteLine("Total elapsed time: {0} ms", stopwatch.ElapsedMilliseconds); 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /ZGuideExamples/tasksink2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading; 7 | 8 | using ZeroMQ; 9 | 10 | namespace Examples 11 | { 12 | static partial class Program 13 | { 14 | public static void TaskSink2(string[] args) 15 | { 16 | // 17 | // Task sink - design 2 18 | // Adds pub-sub flow to send kill signal to workers 19 | // 20 | // Author: metadings 21 | // 22 | 23 | // Socket to receive messages on and 24 | // Socket for worker control 25 | using (var context = new ZContext()) 26 | using (var receiver = new ZSocket(context, ZSocketType.PULL)) 27 | using (var controller = new ZSocket(context, ZSocketType.PUB)) 28 | { 29 | receiver.Bind("tcp://*:5558"); 30 | controller.Bind("tcp://*:5559"); 31 | 32 | // Wait for start of batch 33 | receiver.ReceiveFrame(); 34 | 35 | // Start our clock now 36 | var stopwatch = new Stopwatch(); 37 | stopwatch.Start(); 38 | 39 | // Process 100 confirmations 40 | for (int i = 0; i < 100; ++i) 41 | { 42 | receiver.ReceiveFrame(); 43 | 44 | if ((i / 10) * 10 == i) 45 | Console.Write(":"); 46 | else 47 | Console.Write("."); 48 | } 49 | 50 | stopwatch.Stop(); 51 | Console.WriteLine("Total elapsed time: {0} ms", stopwatch.ElapsedMilliseconds); 52 | 53 | // Send kill signal to workers 54 | controller.Send(new ZFrame("KILL")); 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /ZGuideExamples/taskvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void TaskVent(string[] args) 14 | { 15 | // 16 | // Task ventilator 17 | // Binds PUSH socket to tcp://127.0.0.1:5557 18 | // Sends batch of tasks to workers via that socket 19 | // 20 | // Author: metadings 21 | // 22 | 23 | // Socket to send messages on and 24 | // Socket to send start of batch message on 25 | using (var context = new ZContext()) 26 | using (var sender = new ZSocket(context, ZSocketType.PUSH)) 27 | using (var sink = new ZSocket(context, ZSocketType.PUSH)) 28 | { 29 | sender.Bind("tcp://*:5557"); 30 | sink.Connect("tcp://127.0.0.1:5558"); 31 | 32 | Console.WriteLine("Press ENTER when the workers are ready..."); 33 | Console.ReadKey(true); 34 | Console.WriteLine("Sending tasks to workers..."); 35 | 36 | // The first message is "0" and signals start of batch 37 | sink.Send(new byte[] { 0x00 }, 0, 1); 38 | 39 | // Initialize random number generator 40 | var rnd = new Random(); 41 | 42 | // Send 100 tasks 43 | int i = 0; 44 | long total_msec = 0; // Total expected cost in msecs 45 | for (; i < 100; ++i) 46 | { 47 | // Random workload from 1 to 100msecs 48 | int workload = rnd.Next(100) + 1; 49 | total_msec += workload; 50 | byte[] action = BitConverter.GetBytes(workload); 51 | 52 | Console.WriteLine("{0}", workload); 53 | sender.Send(action, 0, action.Length); 54 | } 55 | 56 | Console.WriteLine("Total expected cost: {0} ms", total_msec); 57 | } 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /ZGuideExamples/taskwork.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void TaskWork(string[] args) 14 | { 15 | // 16 | // Task worker 17 | // Connects PULL socket to tcp://127.0.0.1:5557 18 | // Collects workloads from ventilator via that socket 19 | // Connects PUSH socket to tcp://127.0.0.1:5558 20 | // Sends results to sink via that socket 21 | // 22 | // Author: metadings 23 | // 24 | 25 | // Socket to receive messages on and 26 | // Socket to send messages to 27 | using (var context = new ZContext()) 28 | using (var receiver = new ZSocket(context, ZSocketType.PULL)) 29 | using (var sink = new ZSocket(context, ZSocketType.PUSH)) 30 | { 31 | receiver.Connect("tcp://127.0.0.1:5557"); 32 | sink.Connect("tcp://127.0.0.1:5558"); 33 | 34 | // Process tasks forever 35 | while (true) 36 | { 37 | var replyBytes = new byte[4]; 38 | receiver.ReceiveBytes(replyBytes, 0, replyBytes.Length); 39 | int workload = BitConverter.ToInt32(replyBytes, 0); 40 | Console.WriteLine("{0}.", workload); // Show progress 41 | 42 | Thread.Sleep(workload); // Do the work 43 | 44 | sink.Send(new byte[0], 0, 0); // Send results to sink 45 | } 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /ZGuideExamples/taskwork2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | 9 | namespace Examples 10 | { 11 | static partial class Program 12 | { 13 | public static void TaskWork2(string[] args) 14 | { 15 | // 16 | // Task worker - design 2 17 | // Adds pub-sub flow to receive and respond to kill signal 18 | // 19 | // Author: metadings 20 | // 21 | 22 | // Socket to receive messages on, 23 | // Socket to send messages to and 24 | // Socket for control input 25 | using (var context = new ZContext()) 26 | using (var receiver = new ZSocket(context, ZSocketType.PULL)) 27 | using (var sender = new ZSocket(context, ZSocketType.PUSH)) 28 | using (var controller = new ZSocket(context, ZSocketType.SUB)) 29 | { 30 | receiver.Connect("tcp://127.0.0.1:5557"); 31 | sender.Connect("tcp://127.0.0.1:5558"); 32 | 33 | controller.Connect("tcp://127.0.0.1:5559"); 34 | controller.SubscribeAll(); 35 | 36 | var poll = ZPollItem.CreateReceiver(); 37 | 38 | ZError error; 39 | ZMessage message; 40 | while (true) 41 | { 42 | // Process messages from either socket 43 | if (receiver.PollIn(poll, out message, out error, TimeSpan.FromMilliseconds(64))) 44 | { 45 | int workload = message[0].ReadInt32(); 46 | Console.WriteLine("{0}.", workload); // Show progress 47 | 48 | Thread.Sleep(workload); // Do the work 49 | 50 | sender.Send(new byte[0], 0, 0); // Send results to sink 51 | } 52 | 53 | // Any waiting controller command acts as 'KILL' 54 | if (controller.PollIn(poll, out message, out error, TimeSpan.FromMilliseconds(64))) 55 | { 56 | break; // Exit loop 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /ZGuideExamples/ticlient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Runtime.CompilerServices; 6 | // using System.Runtime.Remoting.Messaging; 7 | using System.Text; 8 | using System.Threading; 9 | using ZeroMQ; 10 | 11 | namespace Examples 12 | { 13 | // Titanic client example 14 | // Implements client side of http://rfc.zeromq.org/spec:9 15 | 16 | // Lets us build this source without creating a library 17 | using MDCliApi; 18 | 19 | static partial class Program 20 | { 21 | 22 | 23 | public static void TIClient(string[] args) 24 | { 25 | CancellationTokenSource cancellor = new CancellationTokenSource(); 26 | Console.CancelKeyPress += (s, ea) => 27 | { 28 | ea.Cancel = true; 29 | cancellor.Cancel(); 30 | }; 31 | 32 | using (MajordomoClient session = new MajordomoClient("tcp://127.0.0.1:5555", Verbose)) 33 | { 34 | // 1. Send 'echo' request to Titanic 35 | ZMessage request = new ZMessage(); 36 | request.Add(new ZFrame("echo")); 37 | request.Add(new ZFrame("Hello World")); 38 | 39 | Guid uuid = Guid.Empty; 40 | using (var reply = TIClient_ServiceCall(session, "titanic.request", request, cancellor)) 41 | { 42 | if (reply != null) 43 | { 44 | uuid = Guid.Parse(reply.PopString()); 45 | "I: request UUID {0}".DumpString(uuid); 46 | } 47 | } 48 | 49 | // 2. Wait until we get a reply 50 | while (!cancellor.IsCancellationRequested) 51 | { 52 | Thread.Sleep(100); 53 | request.Dispose(); 54 | request = new ZMessage(); 55 | request.Add(new ZFrame(uuid.ToString())); 56 | var reply = TIClient_ServiceCall(session, "titanic.reply", request, cancellor); 57 | if (reply != null) 58 | { 59 | string replystring = reply.Last().ToString(); 60 | "Reply: {0}\n".DumpString(replystring); 61 | reply.Dispose(); 62 | 63 | // 3. Close Request 64 | request.Dispose(); 65 | request = new ZMessage(); 66 | request.Add(new ZFrame(uuid.ToString())); 67 | reply = TIClient_ServiceCall(session, "titanic.close", request, cancellor); 68 | reply.Dispose(); 69 | break; 70 | } 71 | else 72 | { 73 | "I: no reply yet, trying again...\n".DumpString(); 74 | Thread.Sleep(5000); // try again in 5 seconds 75 | } 76 | } 77 | } 78 | } 79 | 80 | // Calls a TSP service 81 | // Returns response if successful (status code 200 OK), else NULL 82 | static ZMessage TIClient_ServiceCall (MajordomoClient session, string service, ZMessage request, CancellationTokenSource cts) 83 | { 84 | using (var reply = session.Send(service, request, cts)) 85 | { 86 | if (reply != null) 87 | { 88 | var status = reply.PopString(); 89 | if (status.Equals("200")) 90 | { 91 | return reply.Duplicate(); 92 | } 93 | else if (status.Equals("400")) 94 | { 95 | "E: client fatal error, aborting".DumpString(); 96 | cts.Cancel(); 97 | } 98 | else if (status.Equals("500")) 99 | { 100 | "E: server fatal error, aborting".DumpString(); 101 | cts.Cancel(); 102 | } 103 | } 104 | else 105 | { 106 | cts.Cancel(); // Interrupted or failed 107 | } 108 | } 109 | return null; 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /ZGuideExamples/tripping.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | // using System.Runtime.Remoting.Messaging; 6 | using System.Text; 7 | using System.Threading; 8 | using ZeroMQ; 9 | 10 | namespace Examples 11 | { 12 | static partial class Program 13 | { 14 | // Round-trip demonstrator 15 | // While this example runs in a single process, that is just to make 16 | // it easier to start and stop the example. The client task signals to 17 | // main when it's ready. 18 | public static void Tripping(string[] args) 19 | { 20 | CancellationTokenSource cancellor = new CancellationTokenSource(); 21 | Console.CancelKeyPress += (s, ea) => 22 | { 23 | ea.Cancel = true; 24 | cancellor.Cancel(); 25 | }; 26 | 27 | using (ZContext ctx = new ZContext()) 28 | { 29 | using (var client = new ZActor(ctx, Tripping_ClientTask)) 30 | { 31 | (new Thread(() => Tripping_WorkerTask(ctx))).Start(); 32 | (new Thread(() => Tripping_BrokerTask(ctx))).Start(); 33 | client.Start(); 34 | using (var signal = client.Frontend.ReceiveFrame()) 35 | if (Verbose) 36 | signal.ToString().DumpString(); 37 | } 38 | } 39 | } 40 | 41 | 42 | 43 | static void Tripping_ClientTask(ZContext ctx, ZSocket pipe, CancellationTokenSource cancellor, object[] args) 44 | { 45 | using (ZSocket client = new ZSocket(ctx, ZSocketType.DEALER)) 46 | { 47 | client.Connect("tcp://127.0.0.1:5555"); 48 | "Setting up test...".DumpString(); 49 | Thread.Sleep(100); 50 | 51 | int requests; 52 | "Synchronous round-trip test...".DumpString(); 53 | var start = DateTime.Now; 54 | Stopwatch sw = Stopwatch.StartNew(); 55 | for (requests = 0; requests < 10000; requests++) 56 | { 57 | using (var outgoing = new ZFrame("hello")) 58 | { 59 | client.Send(outgoing); 60 | using (var reply = client.ReceiveFrame()) 61 | { 62 | if (Verbose) 63 | reply.ToString().DumpString(); 64 | } 65 | } 66 | } 67 | sw.Stop(); 68 | " {0} calls - {1} ms => {2} calls / second".DumpString(requests, sw.ElapsedMilliseconds, requests * 1000 / sw.ElapsedMilliseconds); 69 | 70 | "Asynchronous round-trip test...".DumpString(); 71 | sw.Restart(); 72 | for (requests = 0; requests < 100000; requests++) 73 | using (var outgoing = new ZFrame("hello")) 74 | client.SendFrame(outgoing); 75 | 76 | for (requests = 0; requests < 100000; requests++) 77 | using (var reply = client.ReceiveFrame()) 78 | if (Verbose) 79 | reply.ToString().DumpString(); 80 | sw.Stop(); 81 | " {0} calls - {1} ms => {2} calls / second".DumpString(requests, sw.ElapsedMilliseconds, requests * 1000 / sw.ElapsedMilliseconds); 82 | using (var outgoing = new ZFrame("done")) 83 | pipe.SendFrame(outgoing); 84 | } 85 | } 86 | 87 | // .split worker task 88 | // Here is the worker task. All it does is receive a message, and 89 | // bounce it back the way it came: 90 | static void Tripping_WorkerTask(ZContext ctx) 91 | { 92 | using (var worker = new ZSocket(ctx, ZSocketType.DEALER)) 93 | { 94 | worker.Connect("tcp://127.0.0.1:5556"); 95 | 96 | while (true) 97 | { 98 | ZError error; 99 | ZMessage msg = worker.ReceiveMessage(out error); 100 | if (error == null && worker.Send(msg, out error)) 101 | continue; 102 | // errorhandling, context terminated or sth else 103 | if (error.Equals(ZError.ETERM)) 104 | return; // Interrupted 105 | throw new ZException(error); 106 | } 107 | } 108 | } 109 | 110 | // .split broker task 111 | // Here is the broker task. It uses the {{zmq_proxy}} function to switch 112 | // messages between frontend and backend: 113 | static void Tripping_BrokerTask(ZContext ctx) 114 | { 115 | using (var frontend = new ZSocket(ctx, ZSocketType.DEALER)) 116 | using (var backend = new ZSocket(ctx, ZSocketType.DEALER)) 117 | { 118 | frontend.Bind("tcp://*:5555"); 119 | backend.Bind("tcp://*:5556"); 120 | 121 | ZError error; 122 | if (!ZContext.Proxy(frontend, backend, out error)) 123 | { 124 | if (Equals(error, ZError.ETERM)) 125 | return; // Interrupted 126 | throw new ZException(error); 127 | } 128 | } 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /ZGuideExamples/version.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | using ZeroMQ; 8 | using ZeroMQ.lib; 9 | 10 | namespace Examples 11 | { 12 | static partial class Program 13 | { 14 | public static void Version(string[] args) 15 | { 16 | // 17 | // Report 0MQ version 18 | // 19 | // Author: metadings 20 | // 21 | 22 | // Console.WriteLine(zmq.Version); 23 | 24 | int major, minor, patch; 25 | zmq.version(out major, out minor, out patch); 26 | Console.WriteLine("{0}.{1}.{2}", major, minor, patch); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /ZGuideExamples/wuclient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | 6 | using ZeroMQ; 7 | 8 | namespace Examples 9 | { 10 | static partial class Program 11 | { 12 | public static void WUClient(string[] args) 13 | { 14 | // 15 | // Weather update client 16 | // Connects SUB socket to tcp://127.0.0.1:5556 17 | // Collects weather updates and finds avg temp in zipcode 18 | // 19 | // Author: metadings 20 | // 21 | 22 | if (args == null || args.Length < 2) 23 | { 24 | Console.WriteLine(); 25 | Console.WriteLine("Usage: ./{0} WUClient [ZipCode] [Endpoint]", AppDomain.CurrentDomain.FriendlyName); 26 | Console.WriteLine(); 27 | Console.WriteLine(" ZipCode The zip code to subscribe. Default is 72622 Nürtingen"); 28 | Console.WriteLine(" Endpoint Where WUClient should connect to."); 29 | Console.WriteLine(" Default is tcp://127.0.0.1:5556"); 30 | Console.WriteLine(); 31 | if (args.Length < 1) 32 | args = new string[] { "72622", "tcp://127.0.0.1:5556" }; 33 | else 34 | args = new string[] { args[0], "tcp://127.0.0.1:5556" }; 35 | } 36 | 37 | string endpoint = args[1]; 38 | 39 | // Socket to talk to server 40 | using (var context = new ZContext()) 41 | using (var subscriber = new ZSocket(context, ZSocketType.SUB)) 42 | { 43 | string connect_to = args[1]; 44 | Console.WriteLine("I: Connecting to {0}...", connect_to); 45 | subscriber.Connect(connect_to); 46 | 47 | /* foreach (IPAddress address in WUProxy_GetPublicIPs()) 48 | { 49 | var epgmAddress = string.Format("epgm://{0};239.192.1.1:8100", address); 50 | Console.WriteLine("I: Connecting to {0}...", epgmAddress); 51 | subscriber.Connect(epgmAddress); 52 | } 53 | } */ 54 | 55 | // Subscribe to zipcode 56 | string zipCode = args[0]; 57 | Console.WriteLine("I: Subscribing to zip code {0}...", zipCode); 58 | subscriber.Subscribe(zipCode); 59 | 60 | // Process 10 updates 61 | int i = 0; 62 | long total_temperature = 0; 63 | for (; i < 20; ++i) 64 | { 65 | using (var replyFrame = subscriber.ReceiveFrame()) 66 | { 67 | string reply = replyFrame.ReadString(); 68 | 69 | Console.WriteLine(reply); 70 | total_temperature += Convert.ToInt64(reply.Split(' ')[1]); 71 | } 72 | } 73 | Console.WriteLine("Average temperature for zipcode '{0}' was {1}°", zipCode, (total_temperature / i)); 74 | } 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /ZGuideExamples/wuproxy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.NetworkInformation; 6 | using System.Net.Sockets; 7 | using System.Threading; 8 | 9 | using ZeroMQ; 10 | 11 | namespace Examples 12 | { 13 | static partial class Program 14 | { 15 | public static void WUProxy(string[] args) 16 | { 17 | // 18 | // Weather proxy device 19 | // 20 | // Author: metadings 21 | // 22 | 23 | using (var context = new ZContext()) 24 | using (var frontend = new ZSocket(context, ZSocketType.XSUB)) 25 | using (var backend = new ZSocket(context, ZSocketType.XPUB)) 26 | { 27 | // Frontend is where the weather server sits 28 | string localhost = "tcp://127.0.0.1:5556"; 29 | Console.WriteLine("I: Connecting to {0}", localhost); 30 | frontend.Connect(localhost); 31 | 32 | // Backend is our public endpoint for subscribers 33 | foreach (IPAddress address in WUProxy_GetPublicIPs()) 34 | { 35 | var tcpAddress = string.Format("tcp://{0}:8100", address); 36 | Console.WriteLine("I: Binding on {0}", tcpAddress); 37 | backend.Bind(tcpAddress); 38 | 39 | var epgmAddress = string.Format("epgm://{0};239.192.1.1:8100", address); 40 | Console.WriteLine("I: Binding on {0}", epgmAddress); 41 | backend.Bind(epgmAddress); 42 | } 43 | using (var subscription = ZFrame.Create(1)) 44 | { 45 | subscription.Write(new byte[] { 0x1 }, 0, 1); 46 | backend.Send(subscription); 47 | } 48 | 49 | // Run the proxy until the user interrupts us 50 | ZContext.Proxy(frontend, backend); 51 | } 52 | } 53 | 54 | static IEnumerable WUProxy_GetPublicIPs() 55 | { 56 | var list = new List(); 57 | NetworkInterface[] ifaces = NetworkInterface.GetAllNetworkInterfaces(); 58 | foreach (NetworkInterface iface in ifaces) 59 | { 60 | if (iface.NetworkInterfaceType == NetworkInterfaceType.Loopback) 61 | continue; 62 | if (iface.OperationalStatus != OperationalStatus.Up) 63 | continue; 64 | 65 | var props = iface.GetIPProperties(); 66 | var addresses = props.UnicastAddresses; 67 | foreach (UnicastIPAddressInformation address in addresses) 68 | { 69 | if (address.Address.AddressFamily == AddressFamily.InterNetwork) 70 | list.Add(address.Address); 71 | // if (address.Address.AddressFamily == AddressFamily.InterNetworkV6) 72 | // list.Add(address.Address); 73 | } 74 | } 75 | return list; 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /ZGuideExamples/wuserver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Text; 6 | using System.Threading; 7 | 8 | using ZeroMQ; 9 | 10 | namespace Examples 11 | { 12 | static partial class Program 13 | { 14 | public static void WUServer(string[] args) 15 | { 16 | // 17 | // Weather update server 18 | // Binds PUB socket to tcp://*:5556 19 | // Publishes random weather updates 20 | // 21 | // Author: metadings 22 | // 23 | 24 | // Prepare our context and publisher 25 | using (var context = new ZContext()) 26 | using (var publisher = new ZSocket(context, ZSocketType.PUB)) 27 | { 28 | string address = "tcp://*:5556"; 29 | Console.WriteLine("I: Publisher.Bind'ing on {0}", address); 30 | publisher.Bind(address); 31 | 32 | /* foreach (IPAddress localAddress in WUProxy_GetPublicIPs()) 33 | { 34 | var epgmAddress = string.Format("epgm://{0};239.192.1.1:8100", localAddress); 35 | Console.WriteLine("I: Publisher.Bind'ing on {0}...", epgmAddress); 36 | publisher.Bind(epgmAddress); 37 | } */ 38 | 39 | // Initialize random number generator 40 | var rnd = new Random(); 41 | 42 | while (true) 43 | { 44 | // Get values that will fool the boss 45 | int zipcode = rnd.Next(99999); 46 | int temperature = rnd.Next(-55, +45); 47 | 48 | // Send message to all subscribers 49 | var update = string.Format("{0:D5} {1}", zipcode, temperature); 50 | using (var updateFrame = new ZFrame(update)) 51 | { 52 | publisher.Send(updateFrame); 53 | } 54 | } 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /ZPoll.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ 2 | { 3 | using System; 4 | 5 | [Flags] 6 | public enum ZPoll : short 7 | { 8 | None = 0x0, 9 | In = 0x1, 10 | Out = 0x2, 11 | Err = 0x4 12 | } 13 | } -------------------------------------------------------------------------------- /ZPollItem.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ 2 | { 3 | using System; 4 | using System.Threading; 5 | 6 | public class ZPollItem 7 | { 8 | public ZPoll Events; 9 | 10 | public ZPoll ReadyEvents; 11 | 12 | public delegate bool ReceiveDelegate(ZSocket socket, out ZMessage message, out ZError error); 13 | 14 | public ReceiveDelegate ReceiveMessage; 15 | 16 | public static bool DefaultReceiveMessage(ZSocket socket, out ZMessage message, out ZError error) 17 | { 18 | message = null; 19 | return socket.ReceiveMessage(ref message, out error); 20 | } 21 | 22 | public delegate bool SendDelegate(ZSocket socket, ZMessage message, out ZError error); 23 | 24 | public SendDelegate SendMessage; 25 | 26 | public static bool DefaultSendMessage(ZSocket socket, ZMessage message, out ZError error) 27 | { 28 | return socket.Send(message, out error); 29 | } 30 | 31 | protected ZPollItem(ZPoll events) 32 | { 33 | Events = events; 34 | } 35 | 36 | public static ZPollItem Create(ReceiveDelegate receiveMessage) 37 | { 38 | return Create(receiveMessage, null); 39 | } 40 | 41 | public static ZPollItem CreateSender(SendDelegate sendMessage) 42 | { 43 | return Create(null, sendMessage); 44 | } 45 | 46 | public static ZPollItem Create(ReceiveDelegate receiveMessage, SendDelegate sendMessage) 47 | { 48 | var pollItem = new ZPollItem((receiveMessage != null ? ZPoll.In : ZPoll.None) | (sendMessage != null ? ZPoll.Out : ZPoll.None)); 49 | pollItem.ReceiveMessage = receiveMessage; 50 | pollItem.SendMessage = sendMessage; 51 | return pollItem; 52 | } 53 | 54 | public static ZPollItem CreateReceiver() 55 | { 56 | return Create(DefaultReceiveMessage, null); 57 | } 58 | 59 | public static ZPollItem CreateSender() 60 | { 61 | return Create(null, DefaultSendMessage); 62 | } 63 | 64 | public static ZPollItem CreateReceiverSender() 65 | { 66 | return Create(DefaultReceiveMessage, DefaultSendMessage); 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /ZPollItems.Posix.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | using System.Linq; 7 | using System.Threading; 8 | 9 | using lib; 10 | 11 | public static partial class ZPollItems // : IDisposable, IList 12 | { 13 | public static class Posix 14 | { 15 | unsafe internal static bool PollMany( 16 | IEnumerable sockets, 17 | IEnumerable items, ZPoll pollEvents, 18 | out ZError error, TimeSpan? timeout = null) 19 | { 20 | error = default(ZError); 21 | bool result = false; 22 | int count = items.Count(); 23 | int timeoutMs = !timeout.HasValue ? -1 : (int)timeout.Value.TotalMilliseconds; 24 | 25 | zmq_pollitem_posix_t* natives = stackalloc zmq_pollitem_posix_t[count]; 26 | // fixed (zmq_pollitem_posix_t* natives = managedArray) { 27 | 28 | for (int i = 0; i < count; ++i) 29 | { 30 | ZSocket socket = sockets.ElementAt(i); 31 | ZPollItem item = items.ElementAt(i); 32 | zmq_pollitem_posix_t* native = natives + i; 33 | 34 | native->SocketPtr = socket.SocketPtr; 35 | native->Events = (short)(item.Events & pollEvents); 36 | native->ReadyEvents = (short)ZPoll.None; 37 | } 38 | 39 | while (!(result = (-1 != zmq.poll(natives, count, timeoutMs)))) 40 | { 41 | error = ZError.GetLastErr(); 42 | 43 | if (error == ZError.EINTR) 44 | { 45 | error = default(ZError); 46 | continue; 47 | } 48 | break; 49 | } 50 | 51 | for (int i = 0; i < count; ++i) 52 | { 53 | ZPollItem item = items.ElementAt(i); 54 | zmq_pollitem_posix_t* native = natives + i; 55 | 56 | item.ReadyEvents = (ZPoll)native->ReadyEvents; 57 | } 58 | // } 59 | 60 | return result; 61 | } 62 | 63 | unsafe internal static bool PollSingle( 64 | ZSocket socket, 65 | ZPollItem item, ZPoll pollEvents, 66 | out ZError error, TimeSpan? timeout = null) 67 | { 68 | error = default(ZError); 69 | bool result = false; 70 | int timeoutMs = !timeout.HasValue ? -1 : (int)timeout.Value.TotalMilliseconds; 71 | 72 | zmq_pollitem_posix_t* native = stackalloc zmq_pollitem_posix_t[1]; 73 | // fixed (zmq_pollitem_posix_t* native = managedArray) { 74 | 75 | native->SocketPtr = socket.SocketPtr; 76 | native->Events = (short)(item.Events & pollEvents); 77 | native->ReadyEvents = (short)ZPoll.None; 78 | 79 | while (!(result = (-1 != zmq.poll(native, 1, timeoutMs)))) 80 | { 81 | error = ZError.GetLastErr(); 82 | 83 | if (error == ZError.EINTR) 84 | { 85 | error = default(ZError); 86 | continue; 87 | } 88 | break; 89 | } 90 | 91 | item.ReadyEvents = (ZPoll)native->ReadyEvents; 92 | //} 93 | 94 | return result; 95 | } 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /ZPollItems.Win32.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | using System.Linq; 7 | using System.Threading; 8 | 9 | using lib; 10 | 11 | public static partial class ZPollItems // : IDisposable, IList 12 | { 13 | public static class Win32 14 | { 15 | unsafe internal static bool PollMany( 16 | IEnumerable sockets, 17 | IEnumerable items, ZPoll pollEvents, 18 | out ZError error, TimeSpan? timeout = null) 19 | { 20 | error = default(ZError); 21 | bool result = false; 22 | int count = items.Count(); 23 | int timeoutMs = !timeout.HasValue ? -1 : (int)timeout.Value.TotalMilliseconds; 24 | 25 | zmq_pollitem_windows_t* natives = stackalloc zmq_pollitem_windows_t[count]; 26 | // fixed (zmq_pollitem_windows_t* natives = managedArray) { 27 | 28 | for (int i = 0; i < count; ++i) 29 | { 30 | ZSocket socket = sockets.ElementAt(i); 31 | ZPollItem item = items.ElementAt(i); 32 | zmq_pollitem_windows_t* native = natives + i; 33 | 34 | native->SocketPtr = socket.SocketPtr; 35 | native->Events = (short)(item.Events & pollEvents); 36 | native->ReadyEvents = (short)ZPoll.None; 37 | } 38 | 39 | while (!(result = (-1 != zmq.poll(natives, count, timeoutMs)))) 40 | { 41 | error = ZError.GetLastErr(); 42 | 43 | // No Signalling on Windows 44 | /* if (error == ZmqError.EINTR) { 45 | error = ZmqError.DEFAULT; 46 | continue; 47 | } */ 48 | break; 49 | } 50 | 51 | for (int i = 0; i < count; ++i) 52 | { 53 | ZPollItem item = items.ElementAt(i); 54 | zmq_pollitem_windows_t* native = natives + i; 55 | 56 | item.ReadyEvents = (ZPoll)native->ReadyEvents; 57 | } 58 | // } 59 | 60 | return result; 61 | } 62 | 63 | unsafe internal static bool PollSingle( 64 | ZSocket socket, 65 | ZPollItem item, ZPoll pollEvents, 66 | out ZError error, TimeSpan? timeout = null) 67 | { 68 | error = default(ZError); 69 | bool result = false; 70 | int timeoutMs = !timeout.HasValue ? -1 : (int)timeout.Value.TotalMilliseconds; 71 | 72 | zmq_pollitem_windows_t* native = stackalloc zmq_pollitem_windows_t[1]; 73 | // fixed (zmq_pollitem_windows_t* native = managedArray) { 74 | 75 | native->SocketPtr = socket.SocketPtr; 76 | native->Events = (short)(item.Events & pollEvents); 77 | native->ReadyEvents = (short)ZPoll.None; 78 | 79 | while (!(result = (-1 != zmq.poll(native, 1, timeoutMs)))) 80 | { 81 | error = ZError.GetLastErr(); 82 | 83 | /* if (error == ZmqError.EINTR) 84 | { 85 | error = default(ZmqError); 86 | continue; 87 | } */ 88 | break; 89 | } 90 | 91 | item.ReadyEvents = (ZPoll)native->ReadyEvents; 92 | // } 93 | 94 | return result; 95 | } 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /ZSocketFlags.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace ZeroMQ 8 | { 9 | [Flags] 10 | public enum ZSocketFlags : int 11 | { 12 | /// 13 | /// No socket flags are specified. 14 | /// 15 | None = 0, 16 | 17 | /// 18 | /// The operation should be performed in non-blocking mode. 19 | /// 20 | DontWait = 1, 21 | 22 | /// 23 | /// The message being sent is a multi-part message, and that further message parts are to follow. 24 | /// 25 | More = 2 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ZSocketOption.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace ZeroMQ 8 | { 9 | public enum ZSocketOption : int 10 | { 11 | AFFINITY = 4, 12 | IDENTITY = 5, 13 | SUBSCRIBE = 6, 14 | UNSUBSCRIBE = 7, 15 | RATE = 8, 16 | RECOVERY_IVL = 9, 17 | SNDBUF = 11, 18 | RCVBUF = 12, 19 | RCVMORE = 13, 20 | FD = 14, 21 | EVENTS = 15, 22 | TYPE = 16, 23 | LINGER = 17, 24 | RECONNECT_IVL = 18, 25 | BACKLOG = 19, 26 | RECONNECT_IVL_MAX = 21, 27 | MAX_MSG_SIZE = 22, 28 | SNDHWM = 23, 29 | RCVHWM = 24, 30 | MULTICAST_HOPS = 25, 31 | RCVTIMEO = 27, 32 | SNDTIMEO = 28, 33 | LAST_ENDPOINT = 32, 34 | ROUTER_MANDATORY = 33, 35 | TCP_KEEPALIVE = 34, 36 | TCP_KEEPALIVE_CNT = 35, 37 | TCP_KEEPALIVE_IDLE = 36, 38 | TCP_KEEPALIVE_INTVL = 37, 39 | IMMEDIATE = 39, 40 | XPUB_VERBOSE = 40, 41 | ROUTER_RAW = 41, 42 | IPV6 = 42, 43 | MECHANISM = 43, 44 | PLAIN_SERVER = 44, 45 | PLAIN_USERNAME = 45, 46 | PLAIN_PASSWORD = 46, 47 | CURVE_SERVER = 47, 48 | CURVE_PUBLICKEY = 48, 49 | CURVE_SECRETKEY = 49, 50 | CURVE_SERVERKEY = 50, 51 | PROBE_ROUTER = 51, 52 | REQ_CORRELATE = 52, 53 | REQ_RELAXED = 53, 54 | CONFLATE = 54, 55 | ZAP_DOMAIN = 55, 56 | ROUTER_HANDOVER = 56, 57 | TOS = 57, 58 | CONNECT_RID = 61, 59 | GSSAPI_SERVER = 62, 60 | GSSAPI_PRINCIPAL = 63, 61 | GSSAPI_SERVICE_PRINCIPAL = 64, 62 | GSSAPI_PLAINTEXT = 65, 63 | HANDSHAKE_IVL = 66, 64 | IDENTITY_FD = 67, 65 | SOCKS_PROXY = 68, 66 | XPUB_NODROP = 69, 67 | BLOCKY = 70, 68 | XPUB_MANUAL = 71, 69 | XPUB_WELCOME_MSG = 72, 70 | STREAM_NOTIFY = 73, 71 | INVERT_MATCHING = 74, 72 | HEARTBEAT_IVL = 75, 73 | HEARTBEAT_TTL = 76, 74 | HEARTBEAT_TIMEOUT = 77, 75 | XPUB_VERBOSE_UNSUBSCRIBE = 78, 76 | CONNECT_TIMEOUT = 79, 77 | TCP_RETRANSMIT_TIMEOUT = 80, 78 | THREAD_SAFE = 81, 79 | 80 | /* Deprecated options and aliases */ 81 | TCP_ACCEPT_FILTER = 38, 82 | IPC_FILTER_PID = 58, 83 | IPC_FILTER_UID = 59, 84 | IPC_FILTER_GID = 60, 85 | IPV4_ONLY = 31, 86 | DELAY_ATTACH_ON_CONNECT = 39, // IMMEDIATE, 87 | NOBLOCK = 1, // DONTWAIT, 88 | FAIL_UNROUTABLE = 33, // ROUTER_MANDATORY, 89 | ROUTER_BEHAVIOR = 33, // ROUTER_MANDATORY, 90 | } 91 | } -------------------------------------------------------------------------------- /ZSocketSetup.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq.Expressions; 6 | using System.Reflection; 7 | 8 | /// 9 | /// Defines a fluent interface for configuring device sockets. 10 | /// 11 | public class ZSocketSetup 12 | { 13 | readonly ZSocket _socket; 14 | readonly List> _socketInitializers; 15 | readonly List _bindings; 16 | readonly List _connections; 17 | 18 | bool _isConfigured; 19 | 20 | public ZSocketSetup(ZSocket socket) 21 | { 22 | if (socket == null) 23 | { 24 | throw new ArgumentNullException("socket"); 25 | } 26 | 27 | _socket = socket; 28 | _socketInitializers = new List>(); 29 | _bindings = new List(); 30 | _connections = new List(); 31 | } 32 | 33 | /// 34 | /// Configure the socket to bind to a given endpoint. See for details. 35 | /// 36 | /// A string representing the endpoint to which the socket will bind. 37 | /// The current object. 38 | public ZSocketSetup Bind(string endpoint) 39 | { 40 | if (endpoint == null) 41 | { 42 | throw new ArgumentNullException("endpoint"); 43 | } 44 | 45 | _bindings.Add(endpoint); 46 | 47 | return this; 48 | } 49 | 50 | /// 51 | /// Configure the socket to connect to a given endpoint. See for details. 52 | /// 53 | /// A string representing the endpoint to which the socket will connect. 54 | /// The current object. 55 | public ZSocketSetup Connect(string endpoint) 56 | { 57 | if (endpoint == null) 58 | { 59 | throw new ArgumentNullException("endpoint"); 60 | } 61 | 62 | _connections.Add(endpoint); 63 | 64 | return this; 65 | } 66 | 67 | public ZSocketSetup SetSocketOption(Expression> property, T value) 68 | { 69 | PropertyInfo propertyInfo; 70 | 71 | if (property.Body is MemberExpression) 72 | { 73 | propertyInfo = ((MemberExpression)property.Body).Member as PropertyInfo; 74 | } 75 | else 76 | { 77 | propertyInfo = ((MemberExpression)((UnaryExpression)property.Body).Operand).Member as PropertyInfo; 78 | } 79 | 80 | if (propertyInfo == null) 81 | { 82 | throw new InvalidOperationException("The specified ZSocket member is not a property: " + property.Body); 83 | } 84 | 85 | _socketInitializers.Add(s => propertyInfo.SetValue(s, value, null)); 86 | 87 | return this; 88 | } 89 | 90 | private byte[] _subscription; 91 | 92 | /// 93 | /// Configure the socket to subscribe to a specific prefix. See for details. 94 | /// 95 | /// A byte array containing the prefix to which the socket will subscribe. 96 | /// The current object. 97 | public ZSocketSetup Subscribe(byte[] prefix) 98 | { 99 | _subscription = prefix; 100 | return this; 101 | } 102 | 103 | /// 104 | /// Configure the socket to subscribe to all incoming messages. See for details. 105 | /// 106 | /// The current object. 107 | public ZSocketSetup SubscribeAll() 108 | { 109 | _subscription = new byte[2] { 0x01, 0x00 }; 110 | return this; 111 | } 112 | 113 | public void Configure() 114 | { 115 | if (_isConfigured) 116 | { 117 | return; 118 | } 119 | 120 | foreach (Action initializer in _socketInitializers) 121 | { 122 | initializer.Invoke(_socket); 123 | } 124 | 125 | _isConfigured = true; 126 | } 127 | 128 | public void BindConnect() 129 | { 130 | foreach (string endpoint in _bindings) 131 | { 132 | _socket.Bind(endpoint); 133 | } 134 | 135 | foreach (string endpoint in _connections) 136 | { 137 | _socket.Connect(endpoint); 138 | } 139 | 140 | if (_subscription != null) 141 | { 142 | // _socket.Subscribe(_subscription); 143 | 144 | using (var subscription = new ZFrame(_subscription)) 145 | { 146 | _socket.Send(subscription); 147 | } 148 | } 149 | } 150 | 151 | public void UnbindDisconnect() 152 | { 153 | 154 | /* if (_subscription != null) 155 | { 156 | _socket.Unsubscribe(_subscription); 157 | } */ 158 | 159 | ZError error; 160 | 161 | foreach (string endpoint in _bindings) 162 | { 163 | _socket.Unbind(endpoint, out error); 164 | } 165 | 166 | foreach (string endpoint in _connections) 167 | { 168 | _socket.Disconnect(endpoint, out error); 169 | } 170 | } 171 | } 172 | } -------------------------------------------------------------------------------- /ZSocketType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace ZeroMQ 8 | { 9 | public enum ZSocketType : int 10 | { 11 | None = -1, 12 | 13 | /// 14 | /// Exclusive Pair 15 | /// 16 | PAIR, 17 | 18 | /// 19 | /// Publish 20 | /// 21 | PUB, 22 | 23 | /// 24 | /// Subscribe 25 | /// 26 | SUB, 27 | 28 | /// 29 | /// Request 30 | /// 31 | REQ, 32 | 33 | /// 34 | /// Reply / Response 35 | /// 36 | REP, 37 | 38 | /// 39 | /// Dealer 40 | /// 41 | DEALER, 42 | 43 | /// 44 | /// Router 45 | /// 46 | /// 47 | /// When receiving messages a socket shall prepend a message 48 | /// part containing the identity of the originating peer to the message before 49 | /// passing it to the application. When sending messages a ZMQ_ROUTER socket shall remove 50 | /// the first part of the message and use it to determine the identity of the peer the message 51 | /// shall be routed to. If the peer does not exist anymore the message shall be silently discarded. 52 | /// 53 | ROUTER, 54 | 55 | /// 56 | /// Pull 57 | /// 58 | PULL, 59 | 60 | /// 61 | /// Push 62 | /// 63 | PUSH, 64 | 65 | /// 66 | /// XPublisher 67 | /// 68 | /// 69 | /// Subscription message is a byte '1' (for subscriptions) or byte '0' (for unsubscriptions) followed by the subscription body. 70 | /// 71 | XPUB, 72 | 73 | /// 74 | /// XSubscriber 75 | /// 76 | /// 77 | /// Subscription message is a byte '1' (for subscriptions) or byte '0' (for unsubscriptions) followed by the subscription body. 78 | /// 79 | XSUB, 80 | 81 | /// 82 | /// Stream 83 | /// 84 | /// 85 | /// 86 | STREAM 87 | } 88 | } -------------------------------------------------------------------------------- /ZSymbol.cs: -------------------------------------------------------------------------------- 1 | // using System.Runtime.Remoting.Messaging; 2 | 3 | namespace ZeroMQ 4 | { 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Reflection; 9 | using System.Runtime.InteropServices; 10 | using lib; 11 | 12 | /// 13 | /// TODO merge this with its sole subclass, ZError 14 | /// 15 | public class ZSymbol 16 | { 17 | internal protected ZSymbol(int errno) 18 | { 19 | this._num = errno; 20 | } 21 | 22 | private int _num; 23 | public int Number { get { return _num; } } 24 | 25 | public string Name 26 | { 27 | get 28 | { 29 | string result; 30 | return _zsymbolToName.TryGetValue(this, out result) ? result : ""; 31 | } 32 | } 33 | 34 | public string Text { get { return Marshal.PtrToStringAnsi(zmq.strerror(_num)); } } 35 | 36 | private static void PickupConstantSymbols(ref IDictionary symbols) 37 | where T : ZSymbol 38 | { 39 | Type type = typeof(T); 40 | 41 | FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public); 42 | 43 | Type codeType = type.GetNestedType("Code", BindingFlags.NonPublic); 44 | 45 | // Pickup constant symbols 46 | foreach (FieldInfo symbolField in fields.Where(f => typeof(ZSymbol).IsAssignableFrom(f.FieldType))) 47 | { 48 | FieldInfo symbolCodeField = codeType.GetField(symbolField.Name); 49 | if (symbolCodeField != null) 50 | { 51 | int symbolNumber = (int)symbolCodeField.GetValue(null); 52 | 53 | var symbol = Activator.CreateInstance( 54 | type, 55 | BindingFlags.NonPublic | BindingFlags.Instance, 56 | null, 57 | new object[] {symbolNumber}, 58 | null); 59 | symbolField.SetValue(null, symbol); 60 | symbols.Add((ZSymbol)symbol, symbolCodeField.Name); 61 | } 62 | } 63 | } 64 | 65 | public static readonly ZSymbol None = default(ZSymbol); 66 | 67 | static ZSymbol() 68 | { 69 | // System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(zmq).TypeHandle); 70 | 71 | IDictionary symbols = new Dictionary(); 72 | 73 | PickupConstantSymbols(ref symbols); 74 | 75 | _zsymbolToName = symbols; 76 | } 77 | 78 | [Obsolete] 79 | public bool IsEmpty() 80 | { 81 | // TODO: what is the intended semantics of this method? The following expression is always false, since default(ZSymbol) == null. 82 | return this == default(ZSymbol); 83 | } 84 | 85 | static IDictionary _zsymbolToName; 86 | 87 | public static IEnumerable Find(string symbol) 88 | { 89 | return _zsymbolToName 90 | .Where(s => s.Value != null && (s.Value == symbol)).Select(x => x.Key); 91 | } 92 | 93 | public static IEnumerable Find(string ns, int num) 94 | { 95 | return _zsymbolToName 96 | .Where(s => s.Value != null && (s.Value.StartsWith(ns) && s.Key._num == num)).Select(x => x.Key); 97 | } 98 | 99 | public override bool Equals(object obj) 100 | { 101 | return ZSymbol.Equals(this, obj); 102 | } 103 | 104 | public new static bool Equals(object a, object b) 105 | { 106 | if (object.ReferenceEquals(a, b)) 107 | { 108 | return true; 109 | } 110 | 111 | var symbolA = a as ZSymbol; 112 | var symbolB = b as ZSymbol; 113 | 114 | return symbolA != null && symbolB != null && symbolA._num == symbolB._num; 115 | } 116 | 117 | public override int GetHashCode() 118 | { 119 | return Number.GetHashCode(); 120 | } 121 | 122 | public override string ToString() 123 | { 124 | return Name + "(" + Number + "): " + Text; 125 | } 126 | 127 | public static implicit operator int(ZSymbol errnum) 128 | { 129 | return errnum.Number; 130 | } 131 | 132 | } 133 | } -------------------------------------------------------------------------------- /ZThread.cs: -------------------------------------------------------------------------------- 1 | namespace ZeroMQ 2 | { 3 | using System; 4 | using System.Diagnostics; 5 | using System.Threading; 6 | 7 | public abstract class ZThread : IDisposable 8 | { 9 | public CancellationTokenSource Cancellor { get; protected set; } 10 | 11 | protected Thread _thread; 12 | 13 | protected bool _disposed; 14 | 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// 18 | protected ZThread() 19 | { } 20 | 21 | /// 22 | /// Finalizes an instance of the class. 23 | /// 24 | ~ZThread() 25 | { 26 | Dispose(false); 27 | } 28 | 29 | /// 30 | /// Gets a value indicating whether the device loop is running. 31 | /// 32 | public bool IsCancellationRequested 33 | { 34 | get { return Cancellor.IsCancellationRequested; } 35 | } 36 | 37 | public virtual void Start() 38 | { 39 | var cancellor = new CancellationTokenSource(); 40 | Start(cancellor); 41 | } 42 | 43 | /// 44 | /// Start the device in the current thread. 45 | /// 46 | /// The has already been disposed. 47 | public virtual void Start(CancellationTokenSource cancellor) 48 | { 49 | EnsureNotDisposed(); 50 | 51 | Cancellor = cancellor; 52 | 53 | if (_thread == null) _thread = new Thread(Run); 54 | _thread.Start(); 55 | } 56 | 57 | /// 58 | /// Blocks the calling thread until the device terminates. 59 | /// 60 | public virtual void Join() 61 | { 62 | EnsureNotDisposed(); 63 | 64 | if (_thread == null) return; 65 | _thread.Join(); 66 | } 67 | 68 | /// 69 | /// Blocks the calling thread until the device terminates. 70 | /// 71 | public virtual bool Join(int ms) 72 | { 73 | EnsureNotDisposed(); 74 | 75 | if (_thread == null) return false; 76 | return _thread.Join(ms); 77 | } 78 | 79 | /// 80 | /// Blocks the calling thread until the device terminates or the specified time elapses. 81 | /// 82 | /// 83 | /// A set to the amount of time to wait for the device to terminate. 84 | /// 85 | /// 86 | /// true if the device terminated; false if the device has not terminated after 87 | /// the amount of time specified by has elapsed. 88 | /// 89 | public virtual bool Join(TimeSpan timeout) 90 | { 91 | EnsureNotDisposed(); 92 | 93 | if (_thread == null) return false; 94 | return _thread.Join(timeout); 95 | } 96 | 97 | /// 98 | /// Stop the device in such a way that it can be restarted. 99 | /// 100 | public virtual void Stop() 101 | { 102 | EnsureNotDisposed(); 103 | 104 | if (_thread != null) 105 | { 106 | Debug.Assert(Cancellor != null); 107 | Cancellor.Cancel(); 108 | } 109 | } 110 | 111 | /// 112 | /// Stop the device and safely terminate the underlying sockets. 113 | /// 114 | public virtual void Close() 115 | { 116 | EnsureNotDisposed(); 117 | 118 | Stop(); 119 | 120 | if (_thread == null) return; 121 | _thread.Join(); 122 | } 123 | 124 | /// 125 | /// Releases all resources used by the current instance, including the frontend and backend sockets. 126 | /// 127 | public void Dispose() 128 | { 129 | Dispose(true); 130 | GC.SuppressFinalize(this); 131 | } 132 | 133 | protected abstract void Run(); 134 | 135 | /// 136 | /// Stops the device and releases the underlying sockets. Optionally disposes of managed resources. 137 | /// 138 | /// true to release both managed and unmanaged resources; false to release only unmanaged resources. 139 | protected virtual void Dispose(bool disposing) 140 | { 141 | if (!_disposed) 142 | { 143 | if (disposing) Close(); 144 | _disposed = true; 145 | } 146 | } 147 | 148 | protected void EnsureNotDisposed() 149 | { 150 | if (_disposed) throw new ObjectDisposedException(GetType().FullName); 151 | } 152 | } 153 | } -------------------------------------------------------------------------------- /ZeroMQ.7z.Release.cmd: -------------------------------------------------------------------------------- 1 | 7z a -tzip -r ZeroMQ.Release.zip -x!bin\Debug -x!.git -x!amd64\v* -x!i386\v* -x!*.nupkg -x!obj -x!ZeroMQ.*.zip -------------------------------------------------------------------------------- /ZeroMQ.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeromq/clrzmq4/e5471f96b8db833ccc5df5e4e99b25291718f191/ZeroMQ.gif -------------------------------------------------------------------------------- /ZeroMQ.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeromq/clrzmq4/e5471f96b8db833ccc5df5e4e99b25291718f191/ZeroMQ.ico -------------------------------------------------------------------------------- /ZeroMQ.mono.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {6FFD872F-A4A4-4EFA-9B4D-4342BA6CF250} 7 | Library 8 | Properties 9 | ZeroMQ 10 | ZeroMQ 11 | v4.0 12 | False 13 | False 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | TRACE;DEBUG 21 | prompt 22 | 4 23 | true 24 | 25 | 1591 26 | 27 | 28 | false 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | bin\Release\ZeroMQ.xml 34 | true 35 | 36 | 1591 37 | 38 | 39 | true 40 | 41 | 42 | ZeroMQ.snk 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /ZeroMQ.netcore.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | true 6 | false 7 | ZeroMQ 8 | ZeroMQ 9 | ZeroMQ.snk 10 | $(DefaultItemExcludes);AssemblyInfo.cs;ZGuideExamples\**\* 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | NETSTANDARD 20 | 21 | 22 | NETCORE 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ZeroMQ.nuspec: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | ZeroMQ 5 | 4.1.0.31 6 | 7 | metadings, Pieter Hintjens, Martin Sustrik 8 | https://github.com/zeromq/clrzmq4/ 9 | 10 | https://raw.githubusercontent.com/zeromq/clrzmq4/master/ZeroMQ.ico 11 | https://raw.githubusercontent.com/zeromq/clrzmq4/master/LICENSE.txt 12 | true 13 | ZeroMQ C# CLR namespace (.NET and mono, Windows and Linux, x86 and amd64) 14 | ZeroMQ 15 | clrzmq4 ZeroMQ ZMQ 0MQ ØMQ Messaging 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /ZeroMQ.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeromq/clrzmq4/e5471f96b8db833ccc5df5e4e99b25291718f191/ZeroMQ.snk -------------------------------------------------------------------------------- /ZeroMQ.targets: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | amd64/libzmq.dll 9 | PreserveNewest 10 | 11 | 12 | 13 | i386/libzmq.dll 14 | PreserveNewest 15 | 16 | 17 | 18 | 19 | 20 | 21 | amd64/libzmq.so 22 | PreserveNewest 23 | 24 | 25 | 29 | 30 | 31 | 32 | 33 | 34 | amd64/libzmq.dylib 35 | PreserveNewest 36 | 37 | 38 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | Analyzers 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /ZeroMQ.zip.Release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | zip -r ZeroMQ.Release.zip * -x bin/Debug\* obj\* .git\* packages\* i386/v\* amd64/v\* *.nupkg ZeroMQ.*.zip ZeroMQ.*.nupkg 3 | 4 | -------------------------------------------------------------------------------- /app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: "{build}" 2 | #platform: AnyCPU 3 | configuration: Release 4 | 5 | #image: 6 | #- Visual Studio 2017 7 | 8 | #cache: 9 | #- c:\Tools\vcpkg\installed 10 | 11 | init: 12 | - cmd: msbuild /version 13 | 14 | install: 15 | - cmd: vcpkg install zeromq:x64-windows 16 | #- cmd: vcpkg integrate install 17 | - cmd: mkdir C:\projects\clrzmq4\bin\Release\amd64 18 | - cmd: mklink /h C:\projects\clrzmq4\bin\Release\amd64\libzmq.dll c:\Tools\vcpkg\installed\x64-windows\bin\libzmq-mt-4_3_3.dll 19 | - cmd: echo "If the mklink command above fails to create a link, look into C:\Tools\vcpkg\installed\x64-windows\bin" 20 | - cmd: echo "there may be a new libzmq-mt-4_n_n.dll file, and do change this appveyor.yml accordingly:" 21 | - cmd: dir /s C:\Tools\vcpkg\installed\x64-windows\*zmq* 22 | 23 | - cmd: nuget restore clrzmq4.vs.sln 24 | 25 | build: 26 | project: clrzmq4.vs.sln 27 | 28 | test_script: 29 | - cmd: .\bin\Release\ZGuideExamples.exe Version 30 | - cmd: .\bin\Release\ZGuideExamples.exe EAgain 31 | - cmd: .\bin\Release\ZGuideExamples.exe Espresso 32 | 33 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | # $TRAVIS_JOB_ID 5 | 6 | # if [ "$(uname)" = "Darwin" ]; then # MacOSX 7 | # else # if [ "$(uname)" = "Linux" ]; then 8 | # fi 9 | 10 | 11 | msbuild clrzmq4.mono.sln /p:Configuration=Release "$2" "$3" "$4" "$5" 12 | 13 | 14 | 15 | #export MONO_TRACE_LISTENER=Console.Out 16 | #mono ./testrunner/NUnit.ConsoleRunner.3.6.1/tools/nunit3-console.exe ./ZeroMQTest/bin/Release/ZeroMQTest.dll 17 | # MONO_OPTIONS="--profile=monocov:outfile=ZeroMQ.cov,+[ZeroMQ]" 18 | # monocov --export-xml=ZeroMQ.cov.xml ZeroMQ.cov 19 | 20 | -------------------------------------------------------------------------------- /clrzmq4.mono.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZeroMQ.mono", "ZeroMQ.mono.csproj", "{6FFD872F-A4A4-4EFA-9B4D-4342BA6CF250}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZGuideExamples.mono", "ZGuideExamples\ZGuideExamples.mono.csproj", "{EF3A0578-42E7-42D2-9D1D-1DF526FE97AB}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {6FFD872F-A4A4-4EFA-9B4D-4342BA6CF250}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {6FFD872F-A4A4-4EFA-9B4D-4342BA6CF250}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {6FFD872F-A4A4-4EFA-9B4D-4342BA6CF250}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {6FFD872F-A4A4-4EFA-9B4D-4342BA6CF250}.Release|Any CPU.Build.0 = Release|Any CPU 18 | {EF3A0578-42E7-42D2-9D1D-1DF526FE97AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {EF3A0578-42E7-42D2-9D1D-1DF526FE97AB}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {EF3A0578-42E7-42D2-9D1D-1DF526FE97AB}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {EF3A0578-42E7-42D2-9D1D-1DF526FE97AB}.Release|Any CPU.Build.0 = Release|Any CPU 22 | EndGlobalSection 23 | EndGlobal 24 | -------------------------------------------------------------------------------- /clrzmq4.netcore.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZeroMQ.netcore", "ZeroMQ.netcore.csproj", "{F5C4F877-ABFF-408C-BF77-8D61D1D38D13}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZGuideExamples.netcore", "ZGuideExamples\ZGuideExamples.netcore.csproj", "{4B72A50C-CA9D-4172-B762-29281B36AD11}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {F5C4F877-ABFF-408C-BF77-8D61D1D38D13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {F5C4F877-ABFF-408C-BF77-8D61D1D38D13}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {F5C4F877-ABFF-408C-BF77-8D61D1D38D13}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {F5C4F877-ABFF-408C-BF77-8D61D1D38D13}.Release|Any CPU.Build.0 = Release|Any CPU 18 | {4B72A50C-CA9D-4172-B762-29281B36AD11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {4B72A50C-CA9D-4172-B762-29281B36AD11}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {4B72A50C-CA9D-4172-B762-29281B36AD11}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {4B72A50C-CA9D-4172-B762-29281B36AD11}.Release|Any CPU.Build.0 = Release|Any CPU 22 | EndGlobalSection 23 | EndGlobal 24 | -------------------------------------------------------------------------------- /clrzmq4.vs.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZeroMQ.vs", "ZeroMQ.vs.csproj", "{6FFD872F-A4A4-4EFA-9B4D-4342BA6CF250}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZGuideExamples.vs", "ZGuideExamples\ZGuideExamples.vs.csproj", "{EF3A0578-42E7-42D2-9D1D-1DF526FE97AB}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {6FFD872F-A4A4-4EFA-9B4D-4342BA6CF250}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {6FFD872F-A4A4-4EFA-9B4D-4342BA6CF250}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {6FFD872F-A4A4-4EFA-9B4D-4342BA6CF250}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {6FFD872F-A4A4-4EFA-9B4D-4342BA6CF250}.Release|Any CPU.Build.0 = Release|Any CPU 18 | {EF3A0578-42E7-42D2-9D1D-1DF526FE97AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {EF3A0578-42E7-42D2-9D1D-1DF526FE97AB}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {EF3A0578-42E7-42D2-9D1D-1DF526FE97AB}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {EF3A0578-42E7-42D2-9D1D-1DF526FE97AB}.Release|Any CPU.Build.0 = Release|Any CPU 22 | EndGlobalSection 23 | EndGlobal 24 | -------------------------------------------------------------------------------- /project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4.1.0-*", 3 | "description": "ZeroMQ/clrzmq4 library", 4 | 5 | "dependencies": { }, 6 | "runtimes": { 7 | "win": { } 8 | }, 9 | "frameworks": { 10 | ".NETFramework,Version=v4.0": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /travis.preinstall.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | # the used libzmq can be configured using different values for INSTALL_LIBZMQ_MACOS 5 | # if value = port install via macports, else install via homebrew 6 | # homebrew has zeromq only as x64 as of 2017-06-29, so it cannot be used (see also https://github.com/travis-ci/travis-ci/issues/5640)- 7 | 8 | if [ "$(uname)" = "Darwin" ] ; then 9 | 10 | if [ "INSTALL_LIBZMQ_MACOS" == "port" ] ; then 11 | wget --retry-connrefused --waitretry=1 -O /tmp/macports.pkg\ 12 | https://github.com/macports/macports-base/releases/download/v2.4.1/MacPorts-2.4.1-10.11-ElCapitan.pkg 13 | sudo installer -pkg /tmp/macports.pkg -target / 14 | export PATH=/opt/local/bin:/opt/local/sbin:$PATH 15 | sudo rm /opt/local/etc/macports/archive_sites.conf 16 | echo "name macports_archives" >archive_sites.conf 17 | echo "name local_archives" >>archive_sites.conf 18 | echo "urls http://packages.macports.org/ http://nue.de.packages.macports.org/" >>archive_sites.conf 19 | sudo cp archive_sites.conf /opt/local/etc/macports/ 20 | 21 | # ignore errors on call to port, since this seems to always fail with "Updating database of binaries failed" 22 | while (sudo port -v install zmq +universal || true) | grep "Error: Port zmq not found" ; do echo "port install zmq failed, retrying" ; done 23 | 24 | else # if [ "INSTALL_LIBZMQ_MACOS" == "brew" ] ; then 25 | 26 | brew update 27 | brew install zeromq # --universal 28 | fi 29 | 30 | else # if [ "$(uname)" = "Linux" ] 31 | 32 | # curl http://download.opensuse.org/repositories/network:/messaging:/zeromq:/release-stable/Debian_9.0/Release.key >Release.key 33 | # sudo apt-key add Release.key 34 | # sudo add-apt-repository "deb http://download.opensuse.org/repositories/network:/messaging:/zeromq:/release-stable/Debian_9.0 ./" 35 | sudo apt-get update 36 | sudo apt-get install libzmq3-dev 37 | fi 38 | 39 | nuget restore clrzmq4.mono.sln 40 | 41 | --------------------------------------------------------------------------------