Skip to content

ZeroMQ Swift Bindings for iOS, macOS, tvOS and watchOS

License

Notifications You must be signed in to change notification settings

Omegacam/SwiftyZeroMQ5

 
 

Repository files navigation

SwiftyZeroMQ5 - ZeroMQ Swift 5 Bindings for iOS, macOS, tvOS and watchOS

CI Status Swift ZeroMQ Platform

License

This library provides easy-to-use iOS, macOS, tvOS and watchOS Swift bindings for the ZeroMQ C++ library. It is written in Swift 5 and features a bundled stable libzmq library. It provides ZeroMQ's low-level API along with an object-oriented API.

WARNING: THIS VERISON USES DRAFT APIS SUCH AS ZMQ_DISH AND ZMQ_RADIO Modified files include:

  • SocketTypes.swift,
  • zmq.h
  • Socket.swift

What is ZeroMQ?

ZeroMQ (also spelled ØMQ, 0MQ or ZMQ) is a high-performance asynchronous messaging library, aimed at use in distributed or concurrent applications. It provides a message queue, but unlike message-oriented middleware, a ZeroMQ system can run without a dedicated message broker. The library's API is designed to resemble that of Berkeley sockets.

Requirements

  • iOS 9+ / macOS 10.11+ / tvOS 9.0+ / watchOS 2.0+
  • Xcode 11.2 and Swift 5
  • Bitcode-enabled Xcode project for non-MacOS

Usage

Please consult the Documentation Manual for more information. Older examples can also be found in the examples github repository.

Version

import SwiftyZeroMQ5

// Print ZeroMQ library and our framework version
let (major, minor, patch, versionString) = SwiftyZeroMQ.version
print("ZeroMQ library version is \(major).\(minor) with patch level .\(patch)")
print("ZeroMQ library version is \(versionString)")
print("SwiftyZeroMQ version is \(SwiftyZeroMQ.frameworkVersion)")

Request-reply Pattern

import SwiftyZeroMQ5

do {
    // Define a TCP endpoint along with the text that we are going to send/recv
    let endpoint     = "tcp://127.0.0.1:5555"
    let textToBeSent = "Hello world"

    // Request socket
    let context      = try SwiftyZeroMQ.Context()
    let requestor    = try context.socket(.request)
    try requestor.connect(endpoint)

    // Reply socket
    let replier      = try context.socket(.reply)
    try replier.bind(endpoint)

    // Send it without waiting and check the reply on other socket
    try requestor.send(string: textToBeSent, options: .dontWait)
    let reply = try replier.recv()
    if reply == textToBeSent {
        print("Match")
    } else {
        print("Mismatch")
    }

} catch {
    print(error)
}

Publish-Subscribe Pattern

private let endpoint = "tcp://127.0.0.1:5550"

let context      = try SwiftyZeroMQ.Context()
let publisher    = try context.socket(.publish)
let subscriber1  = try context.socket(.subscribe)
let subscriber2  = try context.socket(.subscribe)
let subscriber3  = try context.socket(.subscribe)

try publisher.bind(endpoint)
let subscribers = [
    subscriber1: "Subscriber #1",
    subscriber2: "Subscriber #2",
    subscriber3: "Subscriber #3",
]
try subscriber1.connect(endpoint)
try subscriber2.connect(endpoint)
try subscriber3.connect(endpoint)

// Brief wait to let everything hook up
usleep(1000)

// Subscriber #1 and #2 should receive anything
try subscriber2.setSubscribe(nil)

// Subscriber #3 should receive only messages starting with "topic"
try subscriber3.setSubscribe("topic")

// Brief wait to let everything hook up
usleep(250)

let poller = SwiftyZeroMQ.Poller()
try poller.register(socket: subscriber1, flags: .pollIn)
try poller.register(socket: subscriber2, flags: .pollIn)
try poller.register(socket: subscriber3, flags: .pollIn)

func pollAndRecv() throws {
    let socks = try poller.poll(timeout: 1000)
    for subscriber in socks.keys {
        let name = subscribers[subscriber]
        if socks[subscriber] == SwiftyZeroMQ.PollFlags.pollIn {
            let text = try subscriber.recv(options: .dontWait)
            print("\(name): received '\(text)'")
        } else {
            print("\(name): Nothing")
        }
    }
    print("---")
}

// Send a message - expect only sub2 to receive
try publisher.send(string: "message")

// Wait a bit to let the message come through
usleep(100)

try pollAndRecv();

// Send a message - sub2 and sub3 should receive
try publisher.send(string: "topic: test")

// Wait a bit to let the message come through
usleep(100)

try pollAndRecv();

Poller

import SwiftyZeroMQ5

do {
    // Define a TCP endpoint along with the text that we are going to send/recv
    let endpoint     = "tcp://127.0.0.1:5555"

    // Request socket
    let context      = try SwiftyZeroMQ.Context()
    let requestor    = try context.socket(.request)
    try requestor.connect(endpoint)

    // Reply socket
    let replier      = try context.socket(.reply)
    try replier.bind(endpoint)

    // Create a Poller and add both requestor and replier
    let poller       = SwiftyZeroMQ.Poller()
    try poller.register(socket: requestor, flags: [.pollIn, .pollOut])
    try poller.register(socket: replier, flags: [.pollIn, .pollOut])

    try requestor.send(string: "Hello replier!")

    // wait to let request come through
    sleep(1)

    var updates = try poller.poll()
    if updates[replier] == SwiftyZeroMQ.PollFlags.pollIn {
        print("Replier has data to be received.")
    }
    else {
        print("Expected replier to be in pollIn state.")
        return
    }

    try _ = replier.recv()

    updates = try poller.poll()
    if updates[replier] == SwiftyZeroMQ.PollFlags.none {
        print("All data has been received")
    }
    else {
        print("Expected replier to be in none state.")
        return
    }
} catch {
    print(error)
}

Planned Features (aka TODO)

  • More official ZeroMQ examples written
  • More ZeroMQ API wrapped

See Also

Author & License

Copyright (c) 2016-2017 Ahmad M. Zawawi under the MIT license.

A prebuilt iOS, macOS, tvOS and watchOS universal libzmq library is bundled with this library under the LGPL license.

About

ZeroMQ Swift Bindings for iOS, macOS, tvOS and watchOS

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Swift 69.7%
  • C 26.5%
  • Ruby 3.2%
  • Objective-C 0.6%