[ØMQ], also written as ZeroMQ or 0MQ, is an open source (LGPL) [http://www.zeromq.org/] socket/messaging framework. Bindings for version 2.1, 2.2 and 3.2.1, 3.2.4 and 4.0.1 can be found at http://github.com/jdc8/tclzmq The [ØMQ] project has been forked in [Crossroads I/O]. [nanomsg] is a project implemented by the author (or one of the authors) of ZeroMQ as its "successor" using lessons learnt from ZeroMQ. **SYNOPSIS** package require '''Tcl 8.5''' package require '''zmq ?4.0.1?''' * '''zmq context''' ?''contextName''? ?''-io_threads ''? * ''contextName'' '''cget''' ''optionName'' * ''contextName'' '''configure''' ?''optionName''? ?''optionValue optionName optionValue ...''? * ''contextName'' '''destroy''' * ''contextName'' '''get''' ''optionName'' * ''contextName'' '''set''' ''optionName'' ''optionValue'' * '''zmq socket''' ?''socketName''? ''contextName'' ''socketType'' * ''socketName'' '''bind''' ''endPoint'' * ''socketName'' '''cget''' ''optionName'' * ''socketName'' '''close''' * ''socketName'' '''configure''' ?''optionName''? ?''optionValue optionName optionValue ...''? * ''socketName'' '''connect''' ''endPoint'' * ''socketName'' '''destroy''' * ''socketName'' '''disconnect''' ''endPoint'' * ''socketName'' '''dump''' * ''socketName'' '''get''' ''optionName'' * ''socketName'' '''monitor''' ''endPoint'' ?''eventsList''? * ''socketName'' '''readable''' ?''command''? * ''socketName'' '''recv''' ?''flagsList''? * ''socketName'' '''recv_monitor_event''' * ''socketName'' '''recv_msg''' ''message'' ?''flagsList''? * ''socketName'' '''send''' ''data'' ?''flagsList''? * ''socketName'' '''send_msg''' ''message'' ?''flagsList''? * ''socketName'' '''sendmore''' ''data'' ?''flagsList''? * ''socketName'' '''set''' ''optionName'' ''optionValue'' ?''optionSize''? * ''socketName'' '''unbind''' ''endPoint'' * ''socketName'' '''writable''' ?''command''? * '''zmq message''' ?''messageName''? ?''-size ''? ?''-data ''? * ''messageName'' '''cget''' ''optionName'' * ''messageName'' '''close''' * ''messageName'' '''configure''' ?''optionName''? ?''optionValue optionName optionValue ...''? * ''messageName'' '''copy''' ''destinationMessageName'' * ''messageName'' '''data''' * ''messageName'' '''destroy''' * ''messageName'' '''dump''' * ''messageName'' '''get''' ''optionName'' * ''messageName'' '''more''' * ''messageName'' '''move''' ''destinationMessageName'' * ''messageName'' '''recv''' ''socketName'' ?''flagsList''? * ''messageName'' '''send''' ''socketName'' ?''flagsList''? * ''messageName'' '''sendmore''' ''socketName'' ?''flagsList''? * ''messageName'' '''set''' ''optionName'' ''optionValue'' * ''messageName'' '''size''' * '''zmsg add''' ''messageList'' ''data'' * '''zmsg dump''' ''messageList'' * '''zmsg pop''' ''messageListName'' * '''zmsg push''' ''messageList'' ''data'' * '''zmsg recv''' ''socketName'' * '''zmsg send''' ''socketName'' ''messageList'' * '''zmsg unwrap''' ''messageListName'' * '''zmsg wrap''' ''messageList'' ''data'' * '''zmq poll''' ''pollList'' ''timeout'' ?''timeoutUnit''? * '''zmq device''' ''deviceType'' ''inputSocketName'' ''outputSocketName'' * '''zmq''' '''monitor''' ''contextName'' ''socketName'' ''callbackCommand'' ?''eventsList''? * '''zmq version''' * '''zmq errno''' * '''zmq strerror''' ''errorNumber'' * '''zmq max_block_time''' ''blockTime'' **DESCRIPTION** The ''zmq'' package is a wrapper for the ZeroMQ library. ZeroMQ can be found at http://www.zeromq.org. The wrapper is based on version 4.0.1 of the ZeroMQ library. The package is written using ''critcl'' 3. Use this documentation in combination with the ZeroMQ documentation for more details. All sockets in this documentation refer to ZeroMQ sockets. The ZeroMQ API use ''set'' and ''get'' functions to set or get context, socket and message options. This wrapper provides ''set'' and ''get'' methods for contexts, sockets and message for compatibility with the ZeroMQ API but also provides the more Tcl style ''cget'' and ''configure'' methods. The ZeroMQ API uses ''destroy'' for contexts and ''close'' for sockets and messages. This wrapper provides the same methods for compatibility with the ZeroMQ API but also provides a ''destroy'' method for sockets and messages. **Contexts** ***Context PACKAGE COMMANDS*** '''zmq context''' ?''contextName''? ?''-io_threads ''?: This command creates a new ZeroMQ context object and associated Tcl object command whose name is ''contextName'' if specified or auto generated if not specified. The object command will be created under the current namespace if the ''contextName'' is not fully qualified, and in the specified namespace otherwise. The object command name is returned by this command. The object command methods are explained in section '''Context OBJECT METHODS'''. ***Context OBJECT METHODS*** ''contextName'' '''cget''' ''optionName'': Get context option. See '''configure''' method for list of supported options. ''contextName'' '''configure''' ?''optionName''? ?''optionValue optionName optionValue ...''?: Query or modify context options. If no option is specified, returns a list describing all of the available options. If option is specified with no value, then the command returns the value for the specified option. If one or more option-value pairs are specified, then the command modifies the given context option(s) to have the given value(s); in this case the command returns an empty string. Supported options with associated data type are: '''IO_THREADS''': integer '''MAX_SOCKETS''': integer ''contextName'' '''destroy''': Destroy the ZeroMQ context and delete the associated Tcl object command. ''contextName'' '''get''' ''optionName'': Get context option. See '''configure''' method for list of supported options. ''contextName'' '''set''' ''optionName'' ''optionValue'': Set context option. See '''configure''' method for list of supported options. **Sockets** ***Socket PACKAGE COMMANDS*** '''zmq socket''' ?''socketName''? ''contextName'' ''socketType'': This command creates a new ZeroMQ socket object and associated Tcl object command whose name is ''socketName'' if specified or auto generated if not specified within the specified context and of the specified type. The object command will be created under the current namespace if the ''socketName'' is not fully qualified, and in the specified namespace otherwise. The object command name is returned by this command. The object command methods are explained in section '''Socket OBJECT METHODS'''. Valid values for ''socketType'' are: '''DEALER''': '''PAIR''': '''PUB''': '''PULL''': '''PUSH''': '''REP''': '''REQ''': '''ROUTER''': '''STREAM''': '''SUB''': '''XPUB''': '''XSUB''': ***Socket OBJECT METHODS*** ''socketName'' '''bind''' ''endPoint'': Accept connections on a socket for specified endpoint. ''socketName'' '''cget''' ''optionName'': Get socket option. See '''configure''' method for list of supported options. ''socketName'' '''close''': See '''destroy''' method. ''socketName'' '''configure''' ?''optionName''? ?''optionValue optionName optionValue ...''?: Query or modify socket options. If no option is specified, returns a list describing all of the available options. If option is specified with no value, then the command returns the value for the specified option. If one or more option-value pairs are specified, then the command modifies the given socket option(s) to have the given value(s); in this case the command returns an empty string. Supported options with associated data type are: '''AFFINITY''': unsigned wide integer '''BACKLOG''': integer '''EVENTS''': list of poll flags: ''POLLIN'', ''POLLOUT'' or ''POLLERR'' '''ROUTER_MANDATORY''': integer, write-only '''IDENTITY''': binary '''IMMEDIATE''': integer '''LAST_ENDPOINT''': binary, read-only '''LINGER''': integer '''MAXMSGSIZE''': wide integer '''MECHANISM''': enum: ''NULL'', ''PLAIN'', or ''CURVE'', read-only '''MULTICAST_HOPS''': integer '''RATE''': integer '''RCVBUF''': integer '''RCVHWM''': integer '''RCVMORE''': integer, read-only '''RCVTIMEO''': integer '''RECONNECT_IVL''': integer '''RECONNECT_IVL_MAX''': integer '''RECOVERY_IVL''': integer '''ROUTER_MANDATORY''': integer, write-only '''SNDBUF''': integer '''SNDHWM''': integer '''SNDTIMEO''': integer '''SUBSCRIBE''': binary, write-only '''TCP_ACCEPT_FILTER''': string, write-only '''TCP_KEEPALIVE''': integer '''TCP_KEEPALIVE_CNT''': integer '''TCP_KEEPALIVE_IDLE''': integer '''TCP_KEEPALIVE_INTVL''': integer '''TYPE''': integer '''UNSUBSCRIBE''': binary, write-only '''XPUB_VERBOSE''': integer, write-only '''PLAIN_SERVER''': integer '''PLAIN_USERNAME''': string '''PLAIN_PASSWORD''': string '''CURVE_SERVER''': integer '''CURVE_PUBLICKEY''': string '''CURVE_SECRETKEY''': string '''CURVE_SERVERKEY''': string '''PROBE_ROUTER''': integer '''REQ_CORRELATE''': integer '''REQ_RELAXED''': integer '''CONFLATE''': integer, write-only '''ZAP_DOMAIN''': string '''IPV6''': integer ''socketName'' '''connect''' ''endPoint'': Connect to a socket on the specified endpoint. ''socketName'' '''destroy''': Close the ZeroMQ socket and delete the associated Tcl object command. ''socketName'' '''disconnect''' ''endPoint'': Disconnect from a socket on the specified endpoint. ''socketName'' '''dump''': Read message from the socket and return it in human readable debug format. ''socketName'' '''get''' ''optionName'': Get socket option. See '''configure''' method for list of supported options. ''socketName'' '''monitor''' ''endPoint'' ?''eventsList''?: Arrange for monitoring the specified events. If no events are specified, all events are monitored. Monitoring information is available on a socket of type ''PAIR'' on the specified end-point. Known events can be found in '''Socket monitoring''' ''socketName'' '''readable''' ?''command''?: If specified set, or if not specified get, the socket readable callback command. ''socketName'' '''recv''' ?''flagsList''?: Read a message part from the socket and return it as a string. Only the ''DONTWAIT'' flag is supported. ''socketName'' '''recv_monitor_event''': Read a monitor event part from the monitor socket and return it as a dictionary. The socket must be of type ''PAIR'' and must be connected to the end-point passed to the ''socket monitor'' command. The dictionary will contain the triggered event and extra information depending on the triggered event (e.g address, error code, ...). More infomation about monitoring and possible events can be found in '''Socket monitoring'''. ''socketName'' '''recv_msg''' ''message'' ?''flagsList''?: Read a message part from the socket and place it in the specified message object. Only the ''DONTWAIT'' flag is supported. ''socketName'' '''send''' ''data'' ?''flagsList''?: Send the specified data to the socket as message part. Supported flags are ''DONTWAIT'' and ''SNDMORE''. ''socketName'' '''send_msg''' ''message'' ?''flagsList''?: Send the message part in the specified message object to the socket. Supported flags are ''DONTWAIT'' and ''SNDMORE''. ''socketName'' '''sendmore''' ''data'' ?''flagsList''?: Send the specified data to the socket as message part and indicate there are more message parts to come. Supported flags are ''DONTWAIT'' and ''SNDMORE''. ''socketName'' '''set''' ''optionName'' ''optionValue'' ?''optionSize''?: Set socket option. See '''configure''' method for list of supported options. ''socketName'' '''unbind''' ''endPoint'': Stop accepting connections on a socket for the specified endpoint. ''socketName'' '''writable''' ?''command''?: If specified set, or if not specified get, the socket writable callback command. **Messages** ***Message PACKAGE COMMANDS*** '''zmq message''' ?''messageName''? ?''-size ''? ?''-data ''?: This command creates a new ZeroMQ message object and associated Tcl object command whose name is ''messageName'' if specified or auto generated if not specified with specified size and data. The object command will be created under the current namespace if the ''messageName'' is not fully qualified, and in the specified namespace otherwise. The object command name is returned by this command. The object command methods are explained in section '''Message OBJECT METHODS'''. The use of this message type is not needed with the wrapper. Check the '''Socket OBJECT METHODS''' for socket commands directly reading and writing string and '''Message helper functions''' for utility functions to read and write strings. ***Message OBJECT METHODS*** ''messageName'' '''cget''' ''optionName'': Get message option. See '''configure''' method for list of supported options. ''messageName'' '''close''': See '''destroy''' method. ''messageName'' '''configure''' ?''optionName''? ?''optionValue optionName optionValue ...''?: Query or modify message options. If no option is specified, returns a list describing all of the available options. If option is specified with no value, then the command returns the value for the specified option. If one or more option-value pairs are specified, then the command modifies the given message option(s) to have the given value(s); in this case the command returns an empty string. Supported options with associated data type are: '''MORE''': integer, read-only ''messageName'' '''copy''' ''destinationMessageName'': Copy the message to the specified message. ''messageName'' '''data''': Get the message data as a (binary) string. ''messageName'' '''destroy''': Close the ZeroMQ message and delete the associated Tcl object command. ''messageName'' '''dump''': Get the message as a human readable string. ''messageName'' '''get''' ''optionName'': Get message option. See '''configure''' method for list of supported options. ''messageName'' '''more''': Get indication if more messages are to be received as part of a multi part message. ''messageName'' '''move''' ''destinationMessageName'': Move contents to the specified message. ''messageName'' '''recv''' ''socketName'' ?''flagsList''?: Receive a message on the specified socket. Only the ''DONTWAIT'' flag is supported. ''messageName'' '''send''' ''socketName'' ?''flagsList''?: Send a message to the specified socket as message part. Supported flags are ''DONTWAIT'' and ''SNDMORE''. ''messageName'' '''sendmore''' ''socketName'' ?''flagsList''?: Send a message to the specified socket as message part and indicate there are more parts to come as part of a multi part message. Supported flags are ''DONTWAIT'' and ''SNDMORE''. ''messageName'' '''set''' ''optionName'' ''optionValue'': Set message option. See '''configure''' method for list of supported options. ''messageName'' '''size''': Return the size of the message data part. **Multi-part message helper functions** ZeroMQ sends multi-part messages (e.g. when using envelopes). These helper functions can be used to make it easier to handle those. Data is specified as a (binary) string. A multi-part message is specified a a list of (binary) strings. '''zmsg add''' ''messageList'' ''data'': Add a message part to a multi-part message. The updated multi-part message is returned. '''zmsg dump''' ''messageList'': Return the multi-part message in a human readable form. '''zmsg pop''' ''messageListName'': Pop a message part from the beginning of the specified multi-part message. The popped message part is returned and the specified multi-part message is modified. '''zmsg push''' ''messageList'' ''data'': Push a message part to the beginning of a multi-part message. The modified multi-part message is returned. '''zmsg recv''' ''socketName'': Receive a multi-part message on the specified socket. The received message is returned. '''zmsg send''' ''socketName'' ''messageList'': Send a multi-part message to the specified socket. '''zmsg unwrap''' ''messageListName'': Unwrap multi-part message. The unwrapped message part is returned. An empty message-part following the unwrapped message part (e.g as part of an envelope) is also removed. '''zmsg wrap''' ''messageList'' ''data'': Wrap the multi-part message with the specified data. An empty message part is inserted between the specified data and the spoecified multi-part message. **Polling** '''zmq poll''' ''pollList'' ''timeout'' ?''timeoutUnit''?: Poll the specified sockets for the specifed events. A maximum timeout must be specified. If the value of timeout is 0, the command returns immediately. If the value of timeout is -1, the command will block indefinitely until a specified event occurs. The polling list if specified as a list of poll requests. Such a poll request is a list of: 1. socket 1. list of event flags Supported event flags are: '''POLLIN''': '''POLLOUT''': The poll command will return a list in the same format as the input polling list with list items for each item in the original list for which an event occured and in the list of event flags the events which occured. **Devices** '''zmq device''' ''deviceType'' ''inputSocketName'' ''outputSocketName'': Start a built-in ZeroMQ device. Known devices are: '''FORWARDER''': '''QUEUE''': '''STREAMER''': **Socket monitoring** '''zmq''' '''monitor''' ''contextName'' ''socketName'' ''callbackCommand'' ?''eventsList''?: Helper function for monitoring socket events. This function is a wrapper for the ''socket monitor'' and ''socket recv_monitor_event'' commands. The event dictionary as read with the ''socket recv_monitor_event'' is lappended to the callback-command and the callback command is executed each time one of the specified events is triggered for the specified socket. The event-loop must be executed in order to be able to receive monitoring callback in this way. Supported events for monitoring are: '''ACCEPTED''': '''ACCEPT_FAILED''': '''ALL''': '''BIND_FAILED''': '''CLOSED''': '''CLOSE_FAILED''': '''CONNECTED''': '''CONNECT_DELAYED''': '''CONNECT_RETRIED''': '''DISCONNECTED''': '''LISTENING''': **Miscellaneous** '''zmq version''' : Return the ZeroMQ version used by the Tcl wrapper. '''zmq errno''' : Return the last returned ZeroMQ error code. '''zmq strerror''' ''errorNumber'': Return the human readable string for a ZeroMQ error code. '''zmq max_block_time''' ''blockTime'': Set maximum blocking time for the Tcl event loop waiting for ZeroMQ event in micro seconds. Default is 1000 micro seconds. **Examples** A weather data publishing server, also found in the http://zguide.zeromq.org/page:all#Getting-the-Message-Out%|%ZeroMQ Guide%|%: ====== # # Weather update server # Binds PUB socket to tcp:#*:5556 # Publishes random weather updates # package require zmq # Prepare our context and publisher zmq context context zmq socket publisher context PUB publisher bind "tcp://*:5556" if {$::tcl_platform(platform) ne "windows"} { publisher bind "ipc://weather.ipc" } # Initialize random number generator expr {srand([clock seconds])} while {1} { # Get values that will fool the boss set zipcode [expr {int(rand()*100000)}] set temperature [expr {int(rand()*215)-80}] set relhumidity [expr {int(rand()*50)+50}] # Send message to all subscribers set data [format "%05d %d %d" $zipcode $temperature $relhumidity] if {$zipcode eq "10001"} { puts $data } zmq message msg -data $data publisher send_msg msg msg destroy update idletasks } publisher destroy context destroy ====== And the corresponding client: ====== # # Weather update client # Connects SUB socket to tcp:#localhost:5556 # Collects weather updates and finds avg temp in zipcode # package require zmq # Socket to talk to server zmq context context zmq socket subscriber context SUB subscriber connect "tcp://localhost:5556" # Subscribe to zipcode, default is NYC, 10001 if {[llength $argv]} { set filter [lindex $argv 0] } else { set filter "10001" } subscriber setsockopt SUBSCRIBE $filter # Process updates set total_temp 0 for {set update_nbr 0} {$update_nbr < 10} {incr update_nbr} { zmq message msg subscriber recv_msg msg lassign [msg data] zipcode temperature relhumidity puts [msg data] msg close incr total_temp $temperature } puts "Averate temperatur for zipcode $filter was [expr {$total_temp/$update_nbr}]F" subscriber destroy context destroy ====== Or the client rewritten to process the messages from the publisher asynchronously: ====== # # Weather update client # Connects SUB socket to tcp:#localhost:5556 # Collects weather updates and finds avg temp in zipcode # package require zmq # Socket to talk to server zmq context context zmq socket subscriber context SUB subscriber connect "tcp://localhost:5556" # Subscribe to zipcode, default is NYC, 10001 if {[llength $argv]} { set filter [lindex $argv 0] } else { set filter "10001" } proc get_weather {} { global total_temp cnt done set data [subscriber recv] puts $data lassign $data zipcode temperature relhumidity incr total_temp $temperature incr cnt if {$cnt >= 10} { set done 1 } } subscriber setsockopt SUBSCRIBE $filter set total_temp 0 set cnt 0 subscriber readable get_weather # Process updates vwait done puts "Averate temperatur for zipcode $filter was [expr {$total_temp/$cnt}]F" subscriber destroy context destroy ====== More Tcl example can be found in the http://zguide.zeromq.org/page:all%|%ZeroMQ Guide%|%. **Bugs, ideas, feedback** This document, and the package it describes, will undoubtedly contain bugs and other problems. Please report such at the https://github.com/jdc8/tclzmq/issues%|%Github tracker%|%. Please also report any ideas for enhancements you may have for either package and/or documentation. **License** ''zmq'' uses different licenses for different parts of the code. The 'core' of ''zmq'' (located in ''zmq.tcl'') is licensed under LGPLv3. This just means that if you make any changes to how that code works, you must release those changes under the LGPL. If you just use ''zmq'', then you can use any license you want for your own code. Check ''COPYING.LESSER'' for more info. The restrictions imposed by the LGPL make no sense for the 'non-core' functionality in ''zmq'' (derivative code must also be LGPL or GPL), especially for examples, so all 'non-core' code is relicensed under the more permissive BSD license (specifically Modified BSD aka New BSD aka 3-clause BSD), where possible. This means that you can copy this code and build your own apps without needing to license your own code with the LGPL or GPL. Check ''COPYING.BSD'' for more info. **KEYWORDS** RPC, broadcast, communication, inter process communication, message queue, messaging, producer - consumer, publish - subscribe, queue **CATEGORY** Messaging **COPYRIGHT** Copyright (c) Jos Decoster **More examples** A publishing example, also found in the http://zguide.zeromq.org/page:all#Getting-the-Message-Out%|%ØMQ Guide%|%: ====== # # Weather update server # Binds PUB socket to tcp:#*:5556 # Publishes random weather updates # package require zmq # Prepare our context and publisher zmq context context zmq socket publisher context PUB publisher bind "tcp://*:5556" publisher bind "ipc://weather.ipc" # Initialize random number generator expr {srand([clock seconds])} while {1} { # Get values that will fool the boss set zipcode [expr {int(rand()*100000)}] set temperature [expr {int(rand()*215)-80}] set relhumidity [expr {int(rand()*50)+50}] # Send message to all subscribers set data [format "%05d %d %d" $zipcode $temperature $relhumidity] if {$zipcode eq "10001"} { puts $data } zmq message msg -data $data publisher send_msg msg msg close } publisher close context term ====== with corresponding client: ====== # # Weather update client # Connects SUB socket to tcp:#localhost:5556 # Collects weather updates and finds avg temp in zipcode # package require zmq # Socket to talk to server zmq context context zmq socket subscriber context SUB subscriber connect "tcp://localhost:5556" # Subscribe to zipcode, default is NYC, 10001 if {[llength $argv]} { set filter [lindex $argv 0] } else { set filter "10001" } subscriber setsockopt SUBSCRIBE $filter # Process 100 updates set total_temp 0 for {set update_nbr 0} {$update_nbr < 100} {incr update_nbr} { zmq message msg subscriber recv_msg msg lassign [msg data] zipcode temperature relhumidity puts [msg data] msg close incr total_temp $temperature } puts "Averate temperatur for zipcode $filter was [expr {$total_temp/$update_nbr}]F" subscriber close context term ====== Rewriting the client to process the messages from the publisher asynchronously: ====== # # Weather update client # Connects SUB socket to tcp:#localhost:5556 # Collects weather updates and finds avg temp in zipcode # package require zmq # Socket to talk to server zmq context context zmq socket subscriber context SUB subscriber connect "tcp://localhost:5556" # Subscribe to zipcode, default is NYC, 10001 if {[llength $argv]} { set filter [lindex $argv 0] } else { set filter "10001" } proc get_weather {} { global total_temp cnt done set data [subscriber recv] puts $data lassign $data zipcode temperature relhumidity incr total_temp $temperature incr cnt if {$cnt >= 10} { set done 1 } } subscriber setsockopt SUBSCRIBE $filter set total_temp 0 set cnt 0 subscriber readable get_weather # Process 100 updates vwait done puts "Averate temperatur for zipcode $filter was [expr {$total_temp/$cnt}]F" subscriber close context term ====== There is also a Tcl binding [http://github.com/zeromq/zeromq1/blob/master/libtclzmq/zmq.c] for V1.0. ---- '''[AK] - 2012-04-04 16:24:27''' Does this mean that [GSoC Idea: Updated Tcl bindings for ZeroMQ] is out of date ? '''[jdc] - 2012-04-04 18:50:34''' I guess so. All ZeroMQ commands are wrapped and most of the examples are ported to Tcl. Still work to do to make the package thread safe and to improve the asynchronous processing of messages. ---- '''[ABU] - 2012-04-27''' Please, can you provide a Prêt-à-porter package (binaries for Windows, MacOSX) ? Thanks [jdc] Windows 32 or 64 bit? I don't have access to a mac to create a compiled package. [ABU] 32-bit, please Check http://github.com/jdc8/tclzmq/downloads for 32 and 64 bit Windows packages. <>Interprocess Communication | Message Broker