├── .codecov.yml ├── .github ├── FUNDING.yml ├── dependabot.yml └── workflows │ ├── coverage.yml │ ├── darwin.yml │ ├── linux.yml │ └── windows.yml ├── .gitignore ├── AUTHORS ├── CHANGES-v2.adoc ├── CHANGES-v3.adoc ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING ├── LICENSE ├── README.md ├── SECURITY.md ├── UKRAINE.md ├── device.go ├── dialer.go ├── doc.go ├── errors.go ├── errors └── errors.go ├── examples ├── bus │ ├── bus.go │ └── run.sh ├── context │ ├── context.go │ └── run.sh ├── pair │ ├── pair.go │ └── run.sh ├── pipeline │ ├── pipeline.go │ ├── run.ps1 │ └── run.sh ├── pubsub │ ├── pubsub.go │ └── run.sh ├── raw │ ├── client.go │ ├── main.go │ ├── run.sh │ └── server.go ├── reqrep │ ├── reqrep.go │ └── run.sh ├── survey │ ├── run.sh │ └── survey.go └── websocket │ ├── .gitignore │ ├── README.adoc │ ├── main.go │ ├── reqclient.go │ ├── reqhandler.go │ ├── run.sh │ ├── static.go │ ├── subclient.go │ └── subhandler.go ├── go.mod ├── go.sum ├── internal ├── core │ ├── dialer.go │ ├── listener.go │ ├── pipe.go │ ├── pipe_test.go │ └── socket.go └── test │ ├── addrs.go │ ├── certs.go │ ├── certs_test.go │ ├── closed.go │ ├── device_test.go │ ├── dialer_test.go │ ├── listener_test.go │ ├── maxrx.go │ ├── mock.go │ ├── mocksock.go │ ├── must.go │ ├── operations.go │ ├── options.go │ ├── pipeevent_test.go │ ├── raw.go │ ├── transport.go │ └── ttl.go ├── listener.go ├── macat ├── .gitignore ├── README.md ├── macat.1 ├── macat.go ├── macat.txt ├── macat │ ├── main.go │ └── main_test.go └── macat_test.go ├── message.go ├── options.go ├── perf ├── .gitignore ├── Makefile ├── latency.go ├── main.go ├── reqlatency.go └── throughput.go ├── pipe.go ├── protocol.go ├── protocol ├── bus │ ├── bus.go │ └── bus_test.go ├── pair │ ├── pair.go │ └── pair_test.go ├── pair1 │ ├── pair1.go │ └── pair1_test.go ├── protocol.go ├── pub │ ├── pub.go │ └── pub_test.go ├── pull │ ├── pull.go │ └── pull_test.go ├── push │ ├── push.go │ └── push_test.go ├── rep │ ├── rep.go │ └── rep_test.go ├── req │ ├── req.go │ └── req_test.go ├── respondent │ ├── respondent.go │ └── respondent_test.go ├── star │ ├── star.go │ └── star_test.go ├── sub │ ├── sub.go │ └── sub_test.go ├── surveyor │ ├── surveyor.go │ └── surveyor_test.go ├── xbus │ ├── xbus.go │ └── xbus_test.go ├── xpair │ ├── xpair.go │ └── xpair_test.go ├── xpair1 │ ├── xpair1.go │ └── xpair1_test.go ├── xpub │ ├── xpub.go │ └── xpub_test.go ├── xpull │ ├── xpull.go │ └── xpull_test.go ├── xpush │ ├── xpush.go │ └── xpush_test.go ├── xrep │ ├── xrep.go │ └── xrep_test.go ├── xreq │ ├── xreq.go │ └── xreq_test.go ├── xrespondent │ ├── xrespondent.go │ └── xrespondent_test.go ├── xstar │ ├── xstar.go │ └── xstar_test.go ├── xsub │ ├── xsub.go │ └── xsub_test.go └── xsurveyor │ ├── xsurveyor.go │ └── xsurveyor_test.go ├── socket.go ├── test ├── benchmark_test.go ├── certs.go ├── certs_test.go ├── common_test.go ├── device_test.go ├── doc.go ├── scale_test.go ├── transport.go └── util.go ├── transport.go └── transport ├── all └── all.go ├── conn.go ├── connipc.go ├── connipc_posix.go ├── connipc_windows.go ├── handshaker.go ├── inproc ├── inproc.go └── inproc_test.go ├── ipc ├── ipc_options.go ├── ipc_peer_linux.go ├── ipc_peer_linux_test.go ├── ipc_peer_solaris.go ├── ipc_peer_solaris_test.go ├── ipc_peer_unix.go ├── ipc_test.go ├── ipc_unix.go ├── ipc_unix_test.go ├── ipc_windows.go └── ipc_windows_test.go ├── tcp ├── tcp.go └── tcp_test.go ├── tlstcp ├── tlstcp.go └── tlstcp_test.go ├── transport.go ├── ws ├── ws.go ├── ws_specific_test.go └── ws_test.go └── wss ├── wss.go └── wss_test.go /.codecov.yml: -------------------------------------------------------------------------------- 1 | ignore: 2 | - "perf/*" 3 | - "examples/*/*" 4 | - "internal/test/*" 5 | - "test/*" 6 | - "*_test.go" 7 | - "*/perf/* 8 | - "*/examples/* 9 | - "*/test/* 10 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: gdamore 4 | patreon: gedamore 5 | tidelift: go/github.com/nanomsg/mangos 6 | custom: [ "https://staysail.tech/support/mangos/" ] 7 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gomod 4 | directory: / 5 | schedule: 6 | interval: daily 7 | - package-ecosystem: github-actions 8 | directory: / 9 | schedule: 10 | interval: daily 11 | -------------------------------------------------------------------------------- /.github/workflows/coverage.yml: -------------------------------------------------------------------------------- 1 | name: coverage 2 | on: [push] 3 | jobs: 4 | 5 | build: 6 | name: build 7 | runs-on: ${{ matrix.os }} 8 | strategy: 9 | matrix: 10 | os: [ubuntu-latest, macos-latest, windows-latest] 11 | steps: 12 | 13 | - name: Set up Go 14 | uses: actions/setup-go@v5 15 | with: 16 | go-version: '1.22' 17 | id: go 18 | 19 | - name: Check out code into the Go module directory 20 | uses: actions/checkout@v4 21 | 22 | - name: Get dependencies 23 | run: go get -v -t -d ./... 24 | 25 | - name: Build 26 | run: go build -v . 27 | 28 | - name: Test 29 | run: go test -coverpkg="go.nanomsg.org/mangos/v3/..." -covermode=count -coverprofile="coverage.txt" ./... 30 | 31 | - name: Upload coverage to Codecov 32 | uses: codecov/codecov-action@v5.1.2 33 | with: 34 | token: ${{ secrets.CODECOV_TOKEN }} 35 | file: ./coverage.txt 36 | flags: unittests 37 | name: codecov-umbrella 38 | yml: ./codecov.yml 39 | -------------------------------------------------------------------------------- /.github/workflows/darwin.yml: -------------------------------------------------------------------------------- 1 | name: darwin 2 | on: [push] 3 | jobs: 4 | 5 | build: 6 | name: build 7 | runs-on: [ macos-latest ] 8 | steps: 9 | strategy: 10 | matrix: 11 | go: [ '1.22', '1.20', '1.16' ] 12 | steps: 13 | 14 | - name: Set up Go 15 | uses: actions/setup-go@v5 16 | with: 17 | go-version: ${{ matrix.go }} 18 | id: go 19 | 20 | - name: Check out code into the Go module directory 21 | uses: actions/checkout@v4 22 | 23 | - name: Get dependencies 24 | run: go get -v -t -d ./... 25 | 26 | - name: Build 27 | run: go build -v . 28 | 29 | - name: Test 30 | run: go test ./... 31 | -------------------------------------------------------------------------------- /.github/workflows/linux.yml: -------------------------------------------------------------------------------- 1 | name: linux 2 | on: [push] 3 | jobs: 4 | 5 | build: 6 | name: build 7 | runs-on: [ ubuntu-latest ] 8 | strategy: 9 | matrix: 10 | go: [ '1.22', '1.21', '1.20', '1.18', '1.17', '1.16' ] 11 | steps: 12 | 13 | - name: Set up Go 14 | uses: actions/setup-go@v5 15 | with: 16 | go-version: ${{ matrix.go }} 17 | id: go 18 | 19 | - name: Go version 20 | run: go version 21 | 22 | - name: Check out code into the Go module directory 23 | uses: actions/checkout@v4 24 | 25 | - name: Get dependencies 26 | run: go get -v -t -d ./... 27 | 28 | - name: Build 29 | run: go build -v . 30 | 31 | - name: Test 32 | run: go test ./... 33 | -------------------------------------------------------------------------------- /.github/workflows/windows.yml: -------------------------------------------------------------------------------- 1 | name: windows 2 | on: [push] 3 | jobs: 4 | 5 | build: 6 | name: build 7 | runs-on: [ windows-latest ] 8 | strategy: 9 | matrix: 10 | go: [ '1.22', '1.21', '1.20', '1.18' ] 11 | steps: 12 | 13 | - name: Set up Go 14 | uses: actions/setup-go@v5 15 | with: 16 | go-version: ${{ matrix.go }} 17 | id: go 18 | 19 | - name: Check out code into the Go module directory 20 | uses: actions/checkout@v4 21 | 22 | - name: Get dependencies 23 | run: go get -v -t -d ./... 24 | 25 | - name: Build 26 | run: go build -v . 27 | 28 | - name: Test 29 | run: go test ./... 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | mangos.sublime-workspace 2 | mangos.sublime-project 3 | coverage.txt 4 | .idea 5 | .vscode 6 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | List of mangos contributors and authors; these are the copyright holders 2 | for mangos, referred to as The Mangos Authors. 3 | 4 | Garrett D'Amore 5 | Stuart Wallace 6 | Tyler Treat 7 | Ryan Zezeski 8 | Eugene Korenevsky 9 | Dustin Hiatt 10 | wenfang 11 | Anner van Hardenbroek 12 | Gerrit Renker 13 | Rene Kaufmann 14 | Ben Krieger 15 | Hasan Pekdemir 16 | Sega Okhiria 17 | Staysail Systems, Inc. 18 | Capitar IT Group BV 19 | Calvin Lobo 20 | -------------------------------------------------------------------------------- /CHANGES-v3.adoc: -------------------------------------------------------------------------------- 1 | 2 | = Changes in Version 3 3 | 4 | == Import path changed 5 | 6 | Use `go.nanomsg.org/mangos/v3` as the base URL for imports. 7 | 8 | == Go v1.12 Or Better Required 9 | 10 | We're using modules and semantic versions. 11 | These are understood by recent Go versions, and well supported only 12 | in version 1.12 and newer. 13 | It may be possible to make 1.11 or 1.10 work, but it is unsupported. 14 | 15 | == Forward Plans 16 | 17 | The next batch of changes for mangos is likely to add a lot of 18 | convenience routines. Thus we expect to see minor version v3.1 and 19 | so forth. We'll document those changes as they appear here. -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at garrett@damore.org. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | Mangos is primarily the work of Garrett D'Amore, but other people 2 | have contributed to improve it, and we welcome additional contributions. 3 | If you're thinking of contributing, here's what you should know. 4 | 5 | 1. First check to make sure if an issue for the problem you're addressing, 6 | or feature you're adding, has already been filed. If not, file one here: 7 | 8 | https://github.com/nanomsg/mangos/issues 9 | 10 | Please indicate in the description of the issue that you're working on 11 | the issue, so we don't duplicate effort. 12 | 13 | 2. By submitting code to the project, you are asserting that the work is 14 | either your own, or that you are authorized to submit it to this project. 15 | Further, you are asserting that the project may continue to use, modify, 16 | and redistribute your contribution under the terms in the LICENSE file. 17 | 18 | 3. We maintain an "always release ready" stance for the master branch. That 19 | is, at any point in time the tree should be in a state that a release 20 | could be cut, and bisect should never find a point where an issue is 21 | incompletely fixed or addressed. 22 | 23 | # The remaining items below are consequences of the items above. 24 | 25 | 4. All code must pass `go vet`, and be `go fmt` compliant. 26 | 27 | 5. New features should have tests, and the existing tests must continue 28 | to pass. We use the go test framework. 29 | 30 | 6. Every issue must be fixed by at most one git commit, which shall normally 31 | be identified in the first line of the commit message using the syntax 32 | 33 | "fixes # " 34 | 35 | You can have multiple such lines if your commit addresses multiple issues, 36 | but this is normally discouraged. 37 | 38 | 7. No merge commits. Rebase if you need to. 39 | 40 | 8. Additional text may follow the above line(s), separated from them by an 41 | empty line. Normally this is not necessary, since the information should 42 | be in the bug tracking system. Look at the git log to see examples. 43 | 44 | 9. We don't place copyright statements in the individual files, as we have 45 | a blanket copyright statement. Instead, feel free to add your name to the 46 | end of the AUTHORS file. (Please do this, particularly for non-trivial 47 | changes!) 48 | 49 | 10. Submit a GitHub pull request. Ideally just one bug per PR if possible, 50 | and based upon the latest commit in the GitHub master branch. 51 | 52 | 11. We may rebase your changes, including squashing multiple commits, 53 | or ask you to do so, if you have not followed the procedure above, or 54 | if other changes have been made to the tree since you committed. 55 | 56 | Thank you for your contributions! 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mangos™ v3 2 | 3 | [![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)](https://stand-with-ukraine.pp.ua) 4 | [![Linux](https://img.shields.io/github/actions/workflow/status/nanomsg/mangos/linux.yml?branch=master&logoColor=grey&logo=linux&label=)](https://github.com/nanomsg/mangos/actions) 5 | [![Windows](https://img.shields.io/github/actions/workflow/status/nanomsg/mangos/windows.yml?branch=master&logoColor=grey&logo=windows&label=)](https://github.com/nanomsg/mangos/actions) 6 | [![macOS](https://img.shields.io/github/actions/workflow/status/nanomsg/mangos/darwin.yml?branch=master&logoColor=grey&logo=apple&label=)](https://github.com/nanomsg/mangos/actions) 7 | [![Coverage](https://img.shields.io/codecov/c/github/nanomsg/mangos?logoColor=grey&logo=codecov&label=)](https://codecov.io/gh/nanomsg/mangos) 8 | [![Discord](https://img.shields.io/discord/639573728212156478?label=&logo=discord)](https://discord.gg/wewTkby) 9 | [![Documentation](https://img.shields.io/badge/godoc-docs-blue.svg?label=&logo=go)](https://pkg.go.dev/go.nanomsg.org/mangos/v3) 10 | [![License](https://img.shields.io/github/license/nanomsg/mangos.svg?logoColor=silver&logo=opensourceinitiative&label=&color=blue)](https://github.com/nanomsg/mangos/blob/master/LICENSE) 11 | [![Version](https://img.shields.io/github/v/tag/nanomsg/mangos?logo=github&sort=semver&label=)](https://github.com/nanomsg/mangos/releases) 12 | 13 | Please see [here](UKRAINE.md) for an important message for the people of Russia. 14 | 15 | _Mangos™_ is an implementation in pure Go of the _SP_ 16 | (`Scalability Protocols`) messaging system. 17 | These are colloquially known as `nanomsg`. 18 | 19 | > _NOTE_: The import path has changed! Please change any references 20 | > to `go.nanomsg.org/mangos/v3`. 21 | > The old v2 imports will still work for old applications, provided that 22 | > a sufficiently modern version of Go is used. However, no further work 23 | > will be done on earlier versions. 24 | > Earlier versions will still inter-operate with this version, except that 25 | > within the same process the `inproc` transport can only be used by 26 | > consumers using the same version of mangos. 27 | 28 | The modern C implementation of the SP protocols is available as 29 | [NNG™](https://github.com/nanomsg/nng). 30 | 31 | The original implementation of the SP protocols is available as 32 | [nanomsg™](http://www.nanomsg.org). 33 | 34 | Generally (modulo a few caveats) all of these implementations can inter-operate. 35 | 36 | The design is intended to make it easy to add new transports, 37 | as well as new topologies (`protocols` in SP parlance.) 38 | 39 | At present, all the Req/Rep, Pub/Sub, Pair, Bus, Push/Pull, and 40 | Surveyor/Respondent patterns are supported. 41 | This project also supports an experimental protocol called Star. 42 | 43 | Supported transports include TCP, inproc, IPC, WebSocket, WebSocket/TLS and TLS. 44 | 45 | Basic interoperability with nanomsg and NNG has been verified (you can do 46 | so yourself with `nanocat` and `macat`) for all protocols and transports 47 | that _NNG_ and _nanomsg_ support, except for the _ZeroTier_ transport and the PAIRv1 48 | protocol, which are only supported in _NNG_ at this time. 49 | 50 | There are a number of projects that use these products together. 51 | 52 | ## Documentation 53 | 54 | For API documentation, see https://pkg.go.dev/go.nanomsg.org/mangos/v3. 55 | 56 | ## Testing 57 | 58 | This package supports internal self tests, which can be run in 59 | the idiomatic Go way. 60 | (Note that most of the tests are in a test subdirectory.) 61 | 62 | $ go test go.nanomsg.org/mangos/v3/... 63 | 64 | There are also internal benchmarks available: 65 | 66 | $ go test -bench=. go.nanomsg.org/mangos/v3/test 67 | 68 | ## Commercial Support 69 | 70 | [Staysail Systems, Inc.](mailto:info@staysail.tech) offers 71 | [commercial support](http://staysail.tech/support/mangos) for mangos. 72 | 73 | ## Examples 74 | 75 | Some examples are posted in the directories under `examples/` in this project. 76 | 77 | These examples are rewrites (in Go) of Tim Dysinger's 78 | [Getting Started with Nanomsg](http://nanomsg.org/gettingstarted/index.html). 79 | 80 | Running `go doc` in the example directories will yield information about how 81 | to run each example program. 82 | 83 | Enjoy! 84 | 85 | --- 86 | 87 | Copyright 2021 The Mangos Authors 88 | 89 | mangos™, Nanomsg™ and NNG™ are [trademarks](http://nanomsg.org/trademarks.html) of Garrett D'Amore. 90 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | We take security very seriously in mangos, since you may be using it in 4 | Internet-facing applications. 5 | 6 | ## Supported Versions 7 | 8 | Use this section to tell people about which versions of your project are 9 | currently being supported with security updates. 10 | 11 | | Version | Supported | 12 | | ------- | ------------------ | 13 | | 3.x | :white_check_mark: | 14 | | 2.x | :white_check_mark: | 15 | | 1.x | :x: (serious issues only, we recommend everyone use mangos 3.x) | 16 | 17 | ## Reporting a Vulnerability 18 | 19 | To report a vulnerability, please contact us on our discord. 20 | You may also send an email to garrett@damore.org, or info@staysail.tech. 21 | 22 | We will keep the reporter updated on any status updates on a regular basis, 23 | and will respond within two business days for any reported security issue. 24 | -------------------------------------------------------------------------------- /device.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Mangos Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use file except in compliance with the License. 5 | // You may obtain a copy of the license at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package mangos 16 | 17 | // Device is used to create a forwarding loop between two sockets. If the 18 | // same socket is listed (or either socket is nil), then a loopback device 19 | // is established instead. Note that the single socket case is only valid 20 | // for protocols where the underlying protocol can peer for itself (e.g. PAIR, 21 | // or BUS, but not REQ/REP or PUB/SUB!) 22 | // 23 | // If the plumbing is successful, nil will be returned. Two threads will be 24 | // established to forward messages in each direction. If either socket returns 25 | // error on receive or send, the goroutine doing the forwarding will exit. 26 | // This means that closing either socket will generally cause the goroutines 27 | // to exit. Apart from closing the socket(s), no further operations should be 28 | // performed against the socket. 29 | // 30 | // Both sockets should be RAW; use of a "cooked" socket will result in 31 | // ErrNotRaw. 32 | func Device(s1 Socket, s2 Socket) error { 33 | // Is one of the sockets nil? 34 | if s1 == nil { 35 | s1 = s2 36 | } 37 | if s2 == nil { 38 | s2 = s1 39 | } 40 | // At least one must be non-nil 41 | if s1 == nil || s2 == nil { 42 | return ErrClosed 43 | } 44 | 45 | info1 := s1.Info() 46 | info2 := s2.Info() 47 | if (info1.Self != info2.Peer) || (info2.Self != info1.Peer) { 48 | return ErrBadProto 49 | } 50 | 51 | if val, err := s1.GetOption(OptionRaw); err != nil { 52 | return err 53 | } else if raw, ok := val.(bool); !ok || !raw { 54 | return ErrNotRaw 55 | } 56 | if val, err := s2.GetOption(OptionRaw); err != nil { 57 | return err 58 | } else if raw, ok := val.(bool); !ok || !raw { 59 | return ErrNotRaw 60 | } 61 | 62 | go forwarder(s1, s2) 63 | if s2 != s1 { 64 | go forwarder(s2, s1) 65 | } 66 | return nil 67 | } 68 | 69 | // Forwarder takes messages from one socket, and sends them to the other. 70 | // The sockets must be of compatible types, and must be in Raw mode. 71 | func forwarder(fromSock Socket, toSock Socket) { 72 | for { 73 | m, err := fromSock.RecvMsg() 74 | if err != nil { 75 | // Probably closed socket, nothing else we can do. 76 | return 77 | } 78 | 79 | err = toSock.SendMsg(m) 80 | if err != nil { 81 | return 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /dialer.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Mangos Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use file except in compliance with the License. 5 | // You may obtain a copy of the license at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package mangos 16 | 17 | // Dialer is an interface to the underlying dialer for a transport 18 | // and address. 19 | type Dialer interface { 20 | // Close closes the dialer, and removes it from any active socket. 21 | // Further operations on the Dialer will return ErrClosed. 22 | Close() error 23 | 24 | // Dial starts connecting on the address. If a connection fails, 25 | // it will restart. 26 | Dial() error 27 | 28 | // Address returns the string (full URL) of the Listener. 29 | Address() string 30 | 31 | // SetOption sets an option on the Dialer. Setting options 32 | // can only be done before Dial() has been called. 33 | SetOption(name string, value interface{}) error 34 | 35 | // GetOption gets an option value from the Listener. 36 | GetOption(name string) (interface{}, error) 37 | } 38 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Mangos Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use file except in compliance with the License. 5 | // You may obtain a copy of the license at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package mangos provides a pure Go implementation of the Scalability 16 | // Protocols. These are more commonly known as "nanomsg" which is the 17 | // C-based software package that is also their reference implementation. 18 | // 19 | // These protocols facilitate the rapid creation of applications which 20 | // rely on multiple participants in sometimes complex communications 21 | // topologies, including Request/Reply, Publish/Subscribe, Push/Pull, 22 | // Surveyor/Respondent, etc. 23 | // 24 | // For more information, see www.nanomsg.org. 25 | // 26 | package mangos 27 | -------------------------------------------------------------------------------- /errors.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Mangos Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use file except in compliance with the License. 5 | // You may obtain a copy of the license at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package mangos 16 | 17 | import ( 18 | "go.nanomsg.org/mangos/v3/errors" 19 | ) 20 | 21 | // Various error codes. 22 | const ( 23 | ErrBadAddr = errors.ErrBadAddr 24 | ErrBadHeader = errors.ErrBadHeader 25 | ErrBadVersion = errors.ErrBadVersion 26 | ErrTooShort = errors.ErrTooShort 27 | ErrTooLong = errors.ErrTooLong 28 | ErrClosed = errors.ErrClosed 29 | ErrConnRefused = errors.ErrConnRefused 30 | ErrSendTimeout = errors.ErrSendTimeout 31 | ErrRecvTimeout = errors.ErrRecvTimeout 32 | ErrProtoState = errors.ErrProtoState 33 | ErrProtoOp = errors.ErrProtoOp 34 | ErrBadTran = errors.ErrBadTran 35 | ErrBadProto = errors.ErrBadProto 36 | ErrBadOption = errors.ErrBadOption 37 | ErrBadValue = errors.ErrBadValue 38 | ErrGarbled = errors.ErrGarbled 39 | ErrAddrInUse = errors.ErrAddrInUse 40 | ErrBadProperty = errors.ErrBadProperty 41 | ErrTLSNoConfig = errors.ErrTLSNoConfig 42 | ErrTLSNoCert = errors.ErrTLSNoCert 43 | ErrNotRaw = errors.ErrNotRaw 44 | ErrCanceled = errors.ErrCanceled 45 | ErrNoContext = errors.ErrNoContext 46 | ErrNoPeers = errors.ErrNoPeers 47 | ) 48 | -------------------------------------------------------------------------------- /errors/errors.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Mangos Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use file except in compliance with the License. 5 | // You may obtain a copy of the license at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package errors just defines some constant error codes, and is intended 16 | // to be directly imported. It is safe to import using ".", so that 17 | // short names can be used without concern about unrelated namespace 18 | // pollution. 19 | package errors 20 | 21 | type err string 22 | 23 | func (e err) Error() string { 24 | return string(e) 25 | } 26 | 27 | // Predefined error values. 28 | const ( 29 | ErrBadAddr = err("invalid address") 30 | ErrBadHeader = err("invalid header received") 31 | ErrBadVersion = err("invalid protocol version") 32 | ErrTooShort = err("message is too short") 33 | ErrTooLong = err("message is too long") 34 | ErrClosed = err("object closed") 35 | ErrConnRefused = err("connection refused") 36 | ErrSendTimeout = err("send time out") 37 | ErrRecvTimeout = err("receive time out") 38 | ErrProtoState = err("incorrect protocol state") 39 | ErrProtoOp = err("invalid operation for protocol") 40 | ErrBadTran = err("invalid or unsupported transport") 41 | ErrBadProto = err("invalid or unsupported protocol") 42 | ErrBadOption = err("invalid or unsupported option") 43 | ErrBadValue = err("invalid option value") 44 | ErrGarbled = err("message garbled") 45 | ErrAddrInUse = err("address in use") 46 | ErrBadProperty = err("invalid property name") 47 | ErrTLSNoConfig = err("missing TLS configuration") 48 | ErrTLSNoCert = err("missing TLS certificates") 49 | ErrNotRaw = err("socket not raw") 50 | ErrCanceled = err("operation canceled") 51 | ErrNoContext = err("protocol does not support contexts") 52 | ErrNoPeers = err("no connected peers") 53 | ) 54 | -------------------------------------------------------------------------------- /examples/bus/bus.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Mangos Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use file except in compliance with the License. 5 | // You may obtain a copy of the license at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // bus implements a bus example. 16 | // 17 | // To use: 18 | // 19 | // $ go build . 20 | // $ url0=tcp://127.0.0.1:40890 21 | // $ url1=tcp://127.0.0.1:40891 22 | // $ url2=tcp://127.0.0.1:40892 23 | // $ url3=tcp://127.0.0.1:40893 24 | // $ ./bus node0 $url0 $url1 $url2 & node0=$! 25 | // $ ./bus node1 $url1 $url2 $url3 & node1=$! 26 | // $ ./bus node2 $url2 $url3 & node2=$! 27 | // $ ./bus node3 $url3 $url0 & node3=$! 28 | // $ sleep 5 29 | // $ kill $node0 $node1 $node2 $node3 30 | // 31 | package main 32 | 33 | import ( 34 | "fmt" 35 | "os" 36 | "time" 37 | 38 | "go.nanomsg.org/mangos/v3" 39 | "go.nanomsg.org/mangos/v3/protocol/bus" 40 | 41 | // register transports 42 | _ "go.nanomsg.org/mangos/v3/transport/all" 43 | ) 44 | 45 | func die(format string, v ...interface{}) { 46 | fmt.Fprintln(os.Stderr, fmt.Sprintf(format, v...)) 47 | os.Exit(1) 48 | } 49 | 50 | func node(args []string) { 51 | var sock mangos.Socket 52 | var err error 53 | var msg []byte 54 | var x int 55 | 56 | if sock, err = bus.NewSocket(); err != nil { 57 | die("bus.NewSocket: %s", err) 58 | } 59 | if err = sock.Listen(args[2]); err != nil { 60 | die("sock.Listen: %s", err.Error()) 61 | } 62 | 63 | // wait for everyone to start listening 64 | time.Sleep(time.Second) 65 | for x = 3; x < len(args); x++ { 66 | if err = sock.Dial(args[x]); err != nil { 67 | die("socket.Dial: %s", err.Error()) 68 | } 69 | } 70 | 71 | // wait for everyone to join 72 | time.Sleep(time.Second) 73 | 74 | fmt.Printf("%s: SENDING '%s' ONTO BUS\n", args[1], args[1]) 75 | if err = sock.Send([]byte(args[1])); err != nil { 76 | die("sock.Send: %s", err.Error()) 77 | } 78 | for { 79 | if msg, err = sock.Recv(); err != nil { 80 | die("sock.Recv: %s", err.Error()) 81 | } 82 | fmt.Printf("%s: RECEIVED \"%s\" FROM BUS\n", args[1], 83 | string(msg)) 84 | 85 | } 86 | } 87 | 88 | func main() { 89 | if len(os.Args) > 3 { 90 | node(os.Args) 91 | os.Exit(0) 92 | } 93 | fmt.Fprintf(os.Stderr, "Usage: bus ... \n") 94 | os.Exit(1) 95 | } 96 | -------------------------------------------------------------------------------- /examples/bus/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright 2014 The Mangos Authors 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use file except in compliance with the License. 7 | # You may obtain a copy of the license at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | url0=tcp://127.0.0.1:40890 18 | url1=tcp://127.0.0.1:40891 19 | url2=tcp://127.0.0.1:40892 20 | url3=tcp://127.0.0.1:40893 21 | ./bus node0 $url0 $url1 $url2 & node0=$! 22 | ./bus node1 $url1 $url2 $url3 & node1=$! 23 | ./bus node2 $url2 $url3 & node2=$! 24 | ./bus node3 $url3 $url0 & node3=$! 25 | sleep 5 26 | kill $node0 $node1 $node2 $node3 27 | 28 | -------------------------------------------------------------------------------- /examples/context/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright 2014 The Mangos Authors 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use file except in compliance with the License. 7 | # You may obtain a copy of the license at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | url=tcp://127.0.0.1:40899 18 | 19 | ./context server $url & server=$! && sleep 1 20 | 21 | # Start many client requests at the same time 22 | # Note that there are more client requests than worker threads. 23 | # As worker threads become free they start to service other requests 24 | # in the queue. 25 | ./context client $url "John" & c1=$! 26 | ./context client $url "Bill" & c2=$! 27 | ./context client $url "Mary" & c3=$! 28 | ./context client $url "Susan" & c4=$! 29 | ./context client $url "Mark" & c5=$! 30 | 31 | wait $c1 $c2 $c3 $c4 $c5 32 | 33 | kill $server 34 | -------------------------------------------------------------------------------- /examples/pair/pair.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Mangos Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use file except in compliance with the License. 5 | // You may obtain a copy of the license at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // pair implements a pair example. node0 is a listening 16 | // pair socket, and node1 is a dialing pair socket. 17 | // 18 | // To use: 19 | // 20 | // $ go build . 21 | // $ url=tcp://127.0.0.1:40899 22 | // $ ./pair node0 $url & node0=$! 23 | // $ ./pair node1 $url & node1=$! 24 | // $ sleep 3 25 | // $ kill $node0 $node1 26 | // 27 | package main 28 | 29 | import ( 30 | "fmt" 31 | "os" 32 | "time" 33 | 34 | "go.nanomsg.org/mangos/v3" 35 | "go.nanomsg.org/mangos/v3/protocol/pair" 36 | 37 | // register transports 38 | _ "go.nanomsg.org/mangos/v3/transport/all" 39 | ) 40 | 41 | func die(format string, v ...interface{}) { 42 | fmt.Fprintln(os.Stderr, fmt.Sprintf(format, v...)) 43 | os.Exit(1) 44 | } 45 | 46 | func sendName(sock mangos.Socket, name string) { 47 | fmt.Printf("%s: SENDING \"%s\"\n", name, name) 48 | if err := sock.Send([]byte(name)); err != nil { 49 | die("failed sending: %s", err) 50 | } 51 | } 52 | 53 | func recvName(sock mangos.Socket, name string) { 54 | var msg []byte 55 | var err error 56 | if msg, err = sock.Recv(); err == nil { 57 | fmt.Printf("%s: RECEIVED: \"%s\"\n", name, string(msg)) 58 | } 59 | } 60 | 61 | func sendRecv(sock mangos.Socket, name string) { 62 | for { 63 | sock.SetOption(mangos.OptionRecvDeadline, 100*time.Millisecond) 64 | recvName(sock, name) 65 | time.Sleep(time.Second) 66 | sendName(sock, name) 67 | } 68 | } 69 | 70 | func node0(url string) { 71 | var sock mangos.Socket 72 | var err error 73 | if sock, err = pair.NewSocket(); err != nil { 74 | die("can't get new pair socket: %s", err) 75 | } 76 | if err = sock.Listen(url); err != nil { 77 | die("can't listen on pair socket: %s", err.Error()) 78 | } 79 | sendRecv(sock, "node0") 80 | } 81 | 82 | func node1(url string) { 83 | var sock mangos.Socket 84 | var err error 85 | 86 | if sock, err = pair.NewSocket(); err != nil { 87 | die("can't get new pair socket: %s", err.Error()) 88 | } 89 | if err = sock.Dial(url); err != nil { 90 | die("can't dial on pair socket: %s", err.Error()) 91 | } 92 | sendRecv(sock, "node1") 93 | } 94 | 95 | func main() { 96 | if len(os.Args) > 2 && os.Args[1] == "node0" { 97 | node0(os.Args[2]) 98 | os.Exit(0) 99 | } 100 | if len(os.Args) > 2 && os.Args[1] == "node1" { 101 | node1(os.Args[2]) 102 | os.Exit(0) 103 | } 104 | fmt.Fprintf(os.Stderr, "Usage: pair node0|node1 \n") 105 | os.Exit(1) 106 | } 107 | -------------------------------------------------------------------------------- /examples/pair/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright 2014 The Mangos Authors 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use file except in compliance with the License. 7 | # You may obtain a copy of the license at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | url=tcp://127.0.0.1:40899 18 | ./pair node0 $url & node0=$! 19 | ./pair node1 $url & node1=$! 20 | sleep 3 21 | kill $node0 $node1 22 | -------------------------------------------------------------------------------- /examples/pipeline/pipeline.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Mangos Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use file except in compliance with the License. 5 | // You may obtain a copy of the license at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // pipeline implements a one way pipe example. node0 is a listening 16 | // pull socket, and node1 is a dialing push socket. 17 | // 18 | // To use: 19 | // 20 | // $ go build . 21 | // $ url=tcp://127.0.0.1:40899 22 | // $ ./pipeline node0 $url & node0=$! && sleep 1 23 | // $ ./pipeline node1 $url "Hello, World." 24 | // $ ./pipeline node1 $url "Goodbye." 25 | // $ kill $node0 26 | // 27 | package main 28 | 29 | import ( 30 | "fmt" 31 | "os" 32 | "time" 33 | 34 | "go.nanomsg.org/mangos/v3" 35 | "go.nanomsg.org/mangos/v3/protocol/pull" 36 | "go.nanomsg.org/mangos/v3/protocol/push" 37 | 38 | // register transports 39 | _ "go.nanomsg.org/mangos/v3/transport/all" 40 | ) 41 | 42 | func die(format string, v ...interface{}) { 43 | fmt.Fprintln(os.Stderr, fmt.Sprintf(format, v...)) 44 | os.Exit(1) 45 | } 46 | 47 | func node0(url string) { 48 | var sock mangos.Socket 49 | var err error 50 | var msg []byte 51 | if sock, err = pull.NewSocket(); err != nil { 52 | die("can't get new pull socket: %s", err) 53 | } 54 | if err = sock.Listen(url); err != nil { 55 | die("can't listen on pull socket: %s", err.Error()) 56 | } 57 | for { 58 | // Could also use sock.RecvMsg to get header 59 | msg, err = sock.Recv() 60 | if err != nil { 61 | die("cannot receive from mangos Socket: %s", err.Error()) 62 | } 63 | fmt.Printf("NODE0: RECEIVED \"%s\"\n", msg) 64 | 65 | if string(msg) == "STOP" { 66 | fmt.Println("NODE0: STOPPING") 67 | return 68 | } 69 | } 70 | } 71 | 72 | func node1(url string, msg string) { 73 | var sock mangos.Socket 74 | var err error 75 | 76 | if sock, err = push.NewSocket(); err != nil { 77 | die("can't get new push socket: %s", err.Error()) 78 | } 79 | if err = sock.Dial(url); err != nil { 80 | die("can't dial on push socket: %s", err.Error()) 81 | } 82 | fmt.Printf("NODE1: SENDING \"%s\"\n", msg) 83 | if err = sock.Send([]byte(msg)); err != nil { 84 | die("can't send message on push socket: %s", err.Error()) 85 | } 86 | time.Sleep(time.Second / 10) 87 | sock.Close() 88 | } 89 | 90 | func main() { 91 | if len(os.Args) > 2 && os.Args[1] == "node0" { 92 | node0(os.Args[2]) 93 | os.Exit(0) 94 | } 95 | if len(os.Args) > 3 && os.Args[1] == "node1" { 96 | node1(os.Args[2], os.Args[3]) 97 | os.Exit(0) 98 | } 99 | fmt.Fprintf(os.Stderr, 100 | "Usage: pipeline node0|node1 ...\n") 101 | os.Exit(1) 102 | } 103 | -------------------------------------------------------------------------------- /examples/pipeline/run.ps1: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019 The Mangos Authors 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use file except in compliance with the License. 6 | # You may obtain a copy of the license at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | $url = "tcp://127.0.0.1:40899" 17 | Start-Process -FilePath "go" -NoNewWindow -ArgumentList "run pipeline.go node0 $url" 18 | # Sleep a second to allow for the listening socket to establish 19 | Start-Sleep 1 20 | go run pipeline.go node1 $url "Hello, World." 21 | go run pipeline.go node1 $url "Goodbye." 22 | go run pipeline.go node1 $url "STOP" 23 | -------------------------------------------------------------------------------- /examples/pipeline/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright 2019 The Mangos Authors 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use file except in compliance with the License. 7 | # You may obtain a copy of the license at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | url=tcp://127.0.0.1:40899 18 | go run pipeline.go node0 $url 19 | sleep 1 20 | go run pipeline.go node1 $url "Hello, World." 21 | go run pipeline.go node1 $url "Goodbye." 22 | go run pipeline.go node1 $url "STOP" 23 | -------------------------------------------------------------------------------- /examples/pubsub/pubsub.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Mangos Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use file except in compliance with the License. 5 | // You may obtain a copy of the license at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // pubsub implements a publish/subscribe example. server is a listening 16 | // pub socket, and clients are dialing sub sockets. 17 | // 18 | // To use: 19 | // 20 | // $ go build . 21 | // $ url=tcp://127.0.0.1:40899 22 | // $ ./pubsub server $url server & server=$! && sleep 1 23 | // $ ./pubsub client $url client0 & client0=$! 24 | // $ ./pubsub client $url client1 & client1=$! 25 | // $ ./pubsub client $url client2 & client2=$! 26 | // $ sleep 5 27 | // $ kill $server $client0 $client1 $client2 28 | // 29 | package main 30 | 31 | import ( 32 | "fmt" 33 | "os" 34 | "time" 35 | 36 | "go.nanomsg.org/mangos/v3" 37 | "go.nanomsg.org/mangos/v3/protocol/pub" 38 | "go.nanomsg.org/mangos/v3/protocol/sub" 39 | 40 | // register transports 41 | _ "go.nanomsg.org/mangos/v3/transport/all" 42 | ) 43 | 44 | func die(format string, v ...interface{}) { 45 | fmt.Fprintln(os.Stderr, fmt.Sprintf(format, v...)) 46 | os.Exit(1) 47 | } 48 | 49 | func date() string { 50 | return time.Now().Format(time.ANSIC) 51 | } 52 | 53 | func server(url string) { 54 | var sock mangos.Socket 55 | var err error 56 | if sock, err = pub.NewSocket(); err != nil { 57 | die("can't get new pub socket: %s", err) 58 | } 59 | if err = sock.Listen(url); err != nil { 60 | die("can't listen on pub socket: %s", err.Error()) 61 | } 62 | for { 63 | // Could also use sock.RecvMsg to get header 64 | d := date() 65 | fmt.Printf("SERVER: PUBLISHING DATE %s\n", d) 66 | if err = sock.Send([]byte(d)); err != nil { 67 | die("Failed publishing: %s", err.Error()) 68 | } 69 | time.Sleep(time.Second) 70 | } 71 | } 72 | 73 | func client(url string, name string) { 74 | var sock mangos.Socket 75 | var err error 76 | var msg []byte 77 | 78 | if sock, err = sub.NewSocket(); err != nil { 79 | die("can't get new sub socket: %s", err.Error()) 80 | } 81 | if err = sock.Dial(url); err != nil { 82 | die("can't dial on sub socket: %s", err.Error()) 83 | } 84 | // Empty byte array effectively subscribes to everything 85 | err = sock.SetOption(mangos.OptionSubscribe, []byte("")) 86 | if err != nil { 87 | die("cannot subscribe: %s", err.Error()) 88 | } 89 | for { 90 | if msg, err = sock.Recv(); err != nil { 91 | die("Cannot recv: %s", err.Error()) 92 | } 93 | fmt.Printf("CLIENT(%s): RECEIVED %s\n", name, string(msg)) 94 | } 95 | } 96 | 97 | func main() { 98 | if len(os.Args) > 2 && os.Args[1] == "server" { 99 | server(os.Args[2]) 100 | os.Exit(0) 101 | } 102 | if len(os.Args) > 3 && os.Args[1] == "client" { 103 | client(os.Args[2], os.Args[3]) 104 | os.Exit(0) 105 | } 106 | fmt.Fprintf(os.Stderr, "Usage: pubsub server|client \n") 107 | os.Exit(1) 108 | } 109 | -------------------------------------------------------------------------------- /examples/pubsub/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright 2014 The Mangos Authors 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use file except in compliance with the License. 7 | # You may obtain a copy of the license at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | url=tcp://127.0.0.1:40899 18 | ./pubsub server $url server & server=$! && sleep 1 19 | ./pubsub client $url client0 & client0=$! 20 | ./pubsub client $url client1 & client1=$! 21 | ./pubsub client $url client2 & client2=$! 22 | sleep 5 23 | kill $server $client0 $client1 $client2 24 | 25 | 26 | -------------------------------------------------------------------------------- /examples/raw/client.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Mangos Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use file except in compliance with the License. 5 | // You may obtain a copy of the license at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package main 16 | 17 | import ( 18 | "encoding/binary" 19 | "fmt" 20 | "sync" 21 | 22 | "go.nanomsg.org/mangos/v3" 23 | "go.nanomsg.org/mangos/v3/protocol/req" 24 | 25 | // register transports 26 | _ "go.nanomsg.org/mangos/v3/transport/all" 27 | ) 28 | 29 | // synchronize our output messaging so we don't overlap 30 | var lock sync.Mutex 31 | 32 | func clientWorker(url string, id int) { 33 | var sock mangos.Socket 34 | var m *mangos.Message 35 | var err error 36 | 37 | if sock, err = req.NewSocket(); err != nil { 38 | die("can't get new req socket: %s", err.Error()) 39 | } 40 | 41 | // Leave this in Cooked mode! 42 | 43 | if err = sock.Dial(url); err != nil { 44 | die("can't dial on req socket: %s", err.Error()) 45 | } 46 | 47 | // send an empty messsage 48 | m = mangos.NewMessage(1) 49 | if err = sock.SendMsg(m); err != nil { 50 | die("can't send request: %s", err.Error()) 51 | } 52 | 53 | if m, err = sock.RecvMsg(); err != nil { 54 | die("can't recv reply: %s", err.Error()) 55 | } 56 | sock.Close() 57 | 58 | if len(m.Body) != 4 { 59 | die("bad response len: %d", len(m.Body)) 60 | } 61 | 62 | worker := binary.BigEndian.Uint32(m.Body[0:]) 63 | 64 | lock.Lock() 65 | fmt.Printf("Client: %4d Server: %4d\n", id, worker) 66 | lock.Unlock() 67 | } 68 | 69 | func client(url string, nworkers int) { 70 | 71 | var wg sync.WaitGroup 72 | for i := 0; i < nworkers; i++ { 73 | wg.Add(1) 74 | go func(i int) { 75 | defer wg.Done() 76 | clientWorker(url, i) 77 | }(i) 78 | } 79 | wg.Wait() 80 | 81 | } 82 | -------------------------------------------------------------------------------- /examples/raw/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Mangos Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use file except in compliance with the License. 5 | // You may obtain a copy of the license at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // raw implements an example concurrent request/reply server, using 16 | // the raw server socket. (The clients are run using multiple cooked 17 | // sockets.) 18 | // 19 | // To use: 20 | // 21 | // $ go build . 22 | // $ url=tcp://127.0.0.1:40899 23 | // $ nservers=20 24 | // $ nclients=10 25 | // $ ./raw server $url $nservers & pid=$! && sleep 1 26 | // $ ./raw client $url $nclients 27 | // $ kill $pid 28 | // 29 | package main 30 | 31 | import ( 32 | "fmt" 33 | "os" 34 | "strconv" 35 | ) 36 | 37 | func die(format string, v ...interface{}) { 38 | fmt.Fprintln(os.Stderr, fmt.Sprintf(format, v...)) 39 | os.Exit(1) 40 | } 41 | 42 | func main() { 43 | if len(os.Args) > 2 && os.Args[1] == "server" { 44 | nworkers := 16 45 | if len(os.Args) > 3 { 46 | var err error 47 | nworkers, err = strconv.Atoi(os.Args[3]) 48 | if err != nil || nworkers < 1 { 49 | die("bad worker count") 50 | } 51 | } 52 | server(os.Args[2], nworkers) 53 | os.Exit(0) 54 | } 55 | if len(os.Args) > 2 && os.Args[1] == "client" { 56 | nworkers := 1 57 | if len(os.Args) > 3 { 58 | var err error 59 | nworkers, err = strconv.Atoi(os.Args[3]) 60 | if err != nil || nworkers < 1 { 61 | die("bad worker count") 62 | } 63 | } 64 | client(os.Args[2], nworkers) 65 | os.Exit(0) 66 | } 67 | fmt.Fprintf(os.Stderr, "Usage: %s server|client []\n", os.Args[0]) 68 | os.Exit(1) 69 | } 70 | -------------------------------------------------------------------------------- /examples/raw/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright 2015 The Mangos Authors 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use file except in compliance with the License. 7 | # You may obtain a copy of the license at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | url=tcp://127.0.0.1:40899 18 | nservers=20 19 | nclients=10 20 | ./raw server $url $nservers & pid=$! && sleep 1 21 | ./raw client $url $nclients 22 | kill $pid 23 | -------------------------------------------------------------------------------- /examples/raw/server.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Mangos Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use file except in compliance with the License. 5 | // You may obtain a copy of the license at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package main 16 | 17 | import ( 18 | "encoding/binary" 19 | "fmt" 20 | "math/rand" 21 | "sync" 22 | "time" 23 | 24 | "go.nanomsg.org/mangos/v3" 25 | "go.nanomsg.org/mangos/v3/protocol/xrep" 26 | 27 | // register transports 28 | _ "go.nanomsg.org/mangos/v3/transport/all" 29 | ) 30 | 31 | // Our protocol is simple. Request packet is empty. The reply 32 | // is the replier's ID and the time it delayed responding for (us). 33 | 34 | func serverWorker(sock mangos.Socket, id int) { 35 | var err error 36 | 37 | delay := rand.Intn(int(time.Second)) 38 | 39 | for { 40 | var m *mangos.Message 41 | 42 | if m, err = sock.RecvMsg(); err != nil { 43 | return 44 | } 45 | 46 | m.Body = make([]byte, 4) 47 | 48 | time.Sleep(time.Duration(delay)) 49 | 50 | binary.BigEndian.PutUint32(m.Body[0:], uint32(id)) 51 | 52 | if err = sock.SendMsg(m); err != nil { 53 | return 54 | } 55 | } 56 | } 57 | 58 | func server(url string, nworkers int) { 59 | var sock mangos.Socket 60 | var err error 61 | var wg sync.WaitGroup 62 | 63 | rand.Seed(time.Now().UnixNano()) 64 | 65 | if sock, err = xrep.NewSocket(); err != nil { 66 | die("can't get new rep socket: %s", err) 67 | } 68 | if err = sock.Listen(url); err != nil { 69 | die("can't listen on rep socket: %s", err.Error()) 70 | } 71 | wg.Add(nworkers) 72 | fmt.Printf("Starting %d workers\n", nworkers) 73 | for id := 0; id < nworkers; id++ { 74 | go func(id int) { 75 | defer wg.Done() 76 | serverWorker(sock, id) 77 | }(id) 78 | } 79 | wg.Wait() 80 | } 81 | -------------------------------------------------------------------------------- /examples/reqrep/reqrep.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Mangos Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use file except in compliance with the License. 5 | // You may obtain a copy of the license at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // reqprep implements a request/reply example. node0 is a listening 16 | // rep socket, and node1 is a dialing req socket. 17 | // 18 | // To use: 19 | // 20 | // $ go build . 21 | // $ url=tcp://127.0.0.1:40899 22 | // $ ./reqrep node0 $url & node0=$! && sleep 1 23 | // $ ./reqrep node1 $url 24 | // $ kill $node0 25 | // 26 | package main 27 | 28 | import ( 29 | "fmt" 30 | "os" 31 | "time" 32 | 33 | "go.nanomsg.org/mangos/v3" 34 | "go.nanomsg.org/mangos/v3/protocol/rep" 35 | "go.nanomsg.org/mangos/v3/protocol/req" 36 | 37 | // register transports 38 | _ "go.nanomsg.org/mangos/v3/transport/all" 39 | ) 40 | 41 | func die(format string, v ...interface{}) { 42 | fmt.Fprintln(os.Stderr, fmt.Sprintf(format, v...)) 43 | os.Exit(1) 44 | } 45 | 46 | func date() string { 47 | return time.Now().Format(time.ANSIC) 48 | } 49 | 50 | func node0(url string) { 51 | var sock mangos.Socket 52 | var err error 53 | var msg []byte 54 | if sock, err = rep.NewSocket(); err != nil { 55 | die("can't get new rep socket: %s", err) 56 | } 57 | if err = sock.Listen(url); err != nil { 58 | die("can't listen on rep socket: %s", err.Error()) 59 | } 60 | for { 61 | // Could also use sock.RecvMsg to get header 62 | msg, err = sock.Recv() 63 | if err != nil { 64 | die("cannot receive on rep socket: %s", err.Error()) 65 | } 66 | if string(msg) == "DATE" { // no need to terminate 67 | fmt.Println("NODE0: RECEIVED DATE REQUEST") 68 | d := date() 69 | fmt.Printf("NODE0: SENDING DATE %s\n", d) 70 | err = sock.Send([]byte(d)) 71 | if err != nil { 72 | die("can't send reply: %s", err.Error()) 73 | } 74 | } 75 | } 76 | } 77 | 78 | func node1(url string) { 79 | var sock mangos.Socket 80 | var err error 81 | var msg []byte 82 | 83 | if sock, err = req.NewSocket(); err != nil { 84 | die("can't get new req socket: %s", err.Error()) 85 | } 86 | if err = sock.Dial(url); err != nil { 87 | die("can't dial on req socket: %s", err.Error()) 88 | } 89 | fmt.Printf("NODE1: SENDING DATE REQUEST %s\n", "DATE") 90 | if err = sock.Send([]byte("DATE")); err != nil { 91 | die("can't send message on push socket: %s", err.Error()) 92 | } 93 | if msg, err = sock.Recv(); err != nil { 94 | die("can't receive date: %s", err.Error()) 95 | } 96 | fmt.Printf("NODE1: RECEIVED DATE %s\n", string(msg)) 97 | sock.Close() 98 | } 99 | 100 | func main() { 101 | if len(os.Args) > 2 && os.Args[1] == "node0" { 102 | node0(os.Args[2]) 103 | os.Exit(0) 104 | } 105 | if len(os.Args) > 2 && os.Args[1] == "node1" { 106 | node1(os.Args[2]) 107 | os.Exit(0) 108 | } 109 | fmt.Fprintf(os.Stderr, "Usage: reqrep node0|node1 \n") 110 | os.Exit(1) 111 | } 112 | -------------------------------------------------------------------------------- /examples/reqrep/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright 2014 The Mangos Authors 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use file except in compliance with the License. 7 | # You may obtain a copy of the license at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | url=tcp://127.0.0.1:40899 18 | ./reqrep node0 $url & node0=$! && sleep 1 19 | ./reqrep node1 $url 20 | kill $node0 21 | -------------------------------------------------------------------------------- /examples/survey/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright 2014 The Mangos Authors 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use file except in compliance with the License. 7 | # You may obtain a copy of the license at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | url=tcp://127.0.0.1:40899 18 | ./survey server $url server & server=$! 19 | ./survey client $url client0 & client0=$! 20 | ./survey client $url client1 & client1=$! 21 | ./survey client $url client2 & client2=$! 22 | sleep 5 23 | kill $server $client0 $client1 $client2 24 | 25 | -------------------------------------------------------------------------------- /examples/survey/survey.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Mangos Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use file except in compliance with the License. 5 | // You may obtain a copy of the license at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // survey implements a survey example. server is a surveyor listening 16 | // socket, and clients are dialing respondent sockets. 17 | // 18 | // To use: 19 | // 20 | // $ go build . 21 | // $ url=tcp://127.0.0.1:40899 22 | // $ ./survey server $url server & server=$! 23 | // $ ./survey client $url client0 & client0=$! 24 | // $ ./survey client $url client1 & client1=$! 25 | // $ ./survey client $url client2 & client2=$! 26 | // $ sleep 5 27 | // $ kill $server $client0 $client1 $client2 28 | // 29 | package main 30 | 31 | import ( 32 | "fmt" 33 | "os" 34 | "time" 35 | 36 | "go.nanomsg.org/mangos/v3" 37 | "go.nanomsg.org/mangos/v3/protocol/respondent" 38 | "go.nanomsg.org/mangos/v3/protocol/surveyor" 39 | 40 | // register transports 41 | _ "go.nanomsg.org/mangos/v3/transport/all" 42 | ) 43 | 44 | func die(format string, v ...interface{}) { 45 | fmt.Fprintln(os.Stderr, fmt.Sprintf(format, v...)) 46 | os.Exit(1) 47 | } 48 | 49 | func date() string { 50 | return time.Now().Format(time.ANSIC) 51 | } 52 | 53 | func server(url string) { 54 | var sock mangos.Socket 55 | var err error 56 | var msg []byte 57 | if sock, err = surveyor.NewSocket(); err != nil { 58 | die("can't get new surveyor socket: %s", err) 59 | } 60 | if err = sock.Listen(url); err != nil { 61 | die("can't listen on surveyor socket: %s", err.Error()) 62 | } 63 | err = sock.SetOption(mangos.OptionSurveyTime, time.Second/2) 64 | if err != nil { 65 | die("SetOption(): %s", err.Error()) 66 | } 67 | for { 68 | time.Sleep(time.Second) 69 | fmt.Println("SERVER: SENDING DATE SURVEY REQUEST") 70 | if err = sock.Send([]byte("DATE")); err != nil { 71 | die("Failed sending survey: %s", err.Error()) 72 | } 73 | for { 74 | if msg, err = sock.Recv(); err != nil { 75 | break 76 | } 77 | fmt.Printf("SERVER: RECEIVED \"%s\" SURVEY RESPONSE\n", 78 | string(msg)) 79 | } 80 | fmt.Println("SERVER: SURVEY OVER") 81 | } 82 | } 83 | 84 | func client(url string, name string) { 85 | var sock mangos.Socket 86 | var err error 87 | var msg []byte 88 | 89 | if sock, err = respondent.NewSocket(); err != nil { 90 | die("can't get new respondent socket: %s", err.Error()) 91 | } 92 | if err = sock.Dial(url); err != nil { 93 | die("can't dial on respondent socket: %s", err.Error()) 94 | } 95 | for { 96 | if msg, err = sock.Recv(); err != nil { 97 | die("Cannot recv: %s", err.Error()) 98 | } 99 | fmt.Printf("CLIENT(%s): RECEIVED \"%s\" SURVEY REQUEST\n", 100 | name, string(msg)) 101 | 102 | d := date() 103 | fmt.Printf("CLIENT(%s): SENDING DATE SURVEY RESPONSE\n", name) 104 | if err = sock.Send([]byte(d)); err != nil { 105 | die("Cannot send: %s", err.Error()) 106 | } 107 | } 108 | } 109 | 110 | func main() { 111 | if len(os.Args) > 2 && os.Args[1] == "server" { 112 | server(os.Args[2]) 113 | os.Exit(0) 114 | } 115 | if len(os.Args) > 3 && os.Args[1] == "client" { 116 | client(os.Args[2], os.Args[3]) 117 | os.Exit(0) 118 | } 119 | fmt.Fprintf(os.Stderr, "Usage: survey server|client \n") 120 | os.Exit(1) 121 | } 122 | -------------------------------------------------------------------------------- /examples/websocket/.gitignore: -------------------------------------------------------------------------------- 1 | websocket 2 | websocket.exe 3 | -------------------------------------------------------------------------------- /examples/websocket/README.adoc: -------------------------------------------------------------------------------- 1 | This code demonstrates how to use multiple mangos sockets on a single 2 | WebSocket port, sharing an http server instance between a REQ/REP socket, 3 | a PUB/SUB socket, and a static handler. 4 | 5 | See the run.sh script for instructions as to how to run it. 6 | -------------------------------------------------------------------------------- /examples/websocket/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Mangos Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use file except in compliance with the License. 5 | // You may obtain a copy of the license at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // websocket implements a simple websocket server for mangos, demonstrating 16 | // how to use multiplex multiple sockets on a single HTTP server instance. 17 | // 18 | // The server listens, and offers three paths: 19 | // 20 | // - sub/ - SUB socket, publishes a message "PUB