├── .gitattributes
├── .github
├── ISSUE_TEMPLATE.md
├── stale.yml
└── workflows
│ ├── CI.yml
│ ├── prerelease.yml
│ └── release.yml
├── .gitignore
├── .readthedocs.yml
├── .travis.yml
├── AUTHORS.md
├── CONTRIBUTING.md
├── COPYING.LESSER
├── NuGet.Config
├── README.md
├── appveyor.yml
├── codecov.yml
├── docs
├── Images
│ ├── ActorPass.png
│ ├── ActorTrad.png
│ ├── ActorsOut.png
│ ├── Fanout.png
│ ├── NetMQLogo.svg
│ ├── PgmSettingsInWindows.png
│ ├── PubSubUsingTopics.png
│ ├── RequestResponse.png
│ ├── RequestResponse2Receives.png
│ ├── RequestResponse2Sends.png
│ └── XPubXSubDemo.png
├── actor.md
├── async-await.md
├── beacon.md
├── cleanup.md
├── devices.md
├── index.md
├── introduction.md
├── message.md
├── poller.md
├── proactor.md
├── pub-sub.md
├── push-pull.md
├── queue.md
├── receiving-sending.md
├── request-response.md
├── router-dealer.md
├── scheduler.md
├── stream.md
├── timer.md
├── transports.md
└── xpub-xsub.md
├── img
├── NetMQ.ico
├── NetMQLogo-128px.png
├── NetMQLogo-32px.png
├── NetMQLogo-400px.png
├── NetMQLogo-48px.png
├── NetMQLogo-64px.png
├── NetMQLogo.svg
├── NetMQLogoSquare-256px.png
├── NetMQLogoSquare-400px.png
└── NetMQLogoSquare.svg
├── mkdocs.yml
└── src
├── Directory.Build.props
├── Directory.Build.targets
├── Help
└── SandcastleHelpFileProjectForNetMQ.shfbproj
├── NetMQ.Tests
├── ActorTests.cs
├── App.config
├── AssemblyInfo.cs
├── AsyncTests.cs
├── BeaconTests.cs
├── ByteArraySegmentTests.cs
├── CleanupAfterFixture.cs
├── CleanupTests.cs
├── ClientServer.cs
├── Core
│ └── YQueueTests.cs
├── CurveTests.cs
├── EventDelegatorTests.cs
├── ExceptionTests.cs
├── InProcActors
│ ├── AccountJSON
│ │ ├── Account.cs
│ │ ├── AccountAction.cs
│ │ ├── AccountActorTests.cs
│ │ └── AccountShimHandler.cs
│ ├── Echo
│ │ ├── EchoActorTests.cs
│ │ └── EchoShimHandler.cs
│ └── ExceptionShimExample
│ │ ├── ExceptionShimActorTests.cs
│ │ └── ExceptionShimHandler.cs
├── MechanismTests.cs
├── MessageTests.cs
├── MockBufferPool.cs
├── MockCounterPool.cs
├── MsgTests.cs
├── NetMQ.Tests.csproj
├── NetMQCertificateTest.cs
├── NetMQMonitorTests.cs
├── NetMQPollerTest.cs
├── NetMQProactorTests.cs
├── NetMQQueueTests.cs
├── NetworkOrderBitsConverterTests.cs
├── OutgoingSocketExtensionsTests.cs
├── PeerTests.cs
├── PgmTests.cs
├── ProxyTests.cs
├── PubSubTests.cs
├── PushPullTests.cs
├── RadioDish.cs
├── ReceivingSocketExtensionsTests.cs
├── ReqRepTests.cs
├── RequestWithRetryTests.cs
├── RouterTests.cs
├── ScatterGather.cs
├── SocketOptionsTests.cs
├── SocketTests.cs
├── StreamTests.cs
├── ThrowingTraceListener.cs
├── XPubSubTests.cs
└── ZMTPTests.cs
├── NetMQ.sln
├── NetMQ
├── Annotations.cs
├── AsyncReceiveExtensions.cs
├── AtomicCounterPool.cs
├── BufferPool.cs
├── Core
│ ├── Address.cs
│ ├── Command.cs
│ ├── CommandType.cs
│ ├── Config.cs
│ ├── Ctx.cs
│ ├── ErrorHelper.cs
│ ├── HellloMsgSession.cs
│ ├── IMailbox.cs
│ ├── IOObject.cs
│ ├── IOThread.cs
│ ├── IPollEvents.cs
│ ├── IProactorEvents.cs
│ ├── ITimerEvent.cs
│ ├── Mailbox.cs
│ ├── MailboxSafe.cs
│ ├── Mechanisms
│ │ ├── CurveClientMechanism.cs
│ │ ├── CurveMechanismBase.cs
│ │ ├── CurveServerMechanism.cs
│ │ ├── Mechanism.cs
│ │ └── NullMechanism.cs
│ ├── MonitorEvent.cs
│ ├── Options.cs
│ ├── Own.cs
│ ├── Patterns
│ │ ├── Client.cs
│ │ ├── Dealer.cs
│ │ ├── Dish.cs
│ │ ├── Gather.cs
│ │ ├── Pair.cs
│ │ ├── Peer.cs
│ │ ├── Pub.cs
│ │ ├── Pull.cs
│ │ ├── Push.cs
│ │ ├── Radio.cs
│ │ ├── Rep.cs
│ │ ├── Req.cs
│ │ ├── Router.cs
│ │ ├── Scatter.cs
│ │ ├── Server.cs
│ │ ├── Stream.cs
│ │ ├── Sub.cs
│ │ ├── Utils
│ │ │ ├── ArrayExtensions.cs
│ │ │ ├── Distribution.cs
│ │ │ ├── FairQueueing.cs
│ │ │ ├── LoadBalancer.cs
│ │ │ ├── MultiTrie.cs
│ │ │ └── Trie.cs
│ │ ├── XPub.cs
│ │ └── XSub.cs
│ ├── Pipe.cs
│ ├── Reaper.cs
│ ├── SessionBase.cs
│ ├── SocketBase.cs
│ ├── Transports
│ │ ├── ByteArraySegment.cs
│ │ ├── DecoderBase.cs
│ │ ├── EncoderBase.cs
│ │ ├── IDecoder.cs
│ │ ├── IEncoder.cs
│ │ ├── IEngine.cs
│ │ ├── Ipc
│ │ │ ├── IpcAddress.cs
│ │ │ ├── IpcConnector.cs
│ │ │ └── IpcListener.cs
│ │ ├── Pgm
│ │ │ ├── PgmAddress.cs
│ │ │ ├── PgmListener.cs
│ │ │ ├── PgmSender.cs
│ │ │ ├── PgmSession.cs
│ │ │ └── PgmSocket.cs
│ │ ├── RawDecoder.cs
│ │ ├── RawEncoder.cs
│ │ ├── StreamEngine.cs
│ │ ├── Tcp
│ │ │ ├── TcpAddress.cs
│ │ │ ├── TcpConnector.cs
│ │ │ └── TcpListener.cs
│ │ ├── V1Decoder.cs
│ │ ├── V1Encoder.cs
│ │ ├── V2Decoder.cs
│ │ ├── V2Encoder.cs
│ │ ├── V2Protocol.cs
│ │ └── V3Protocol.cs
│ ├── Utils
│ │ ├── AtomicCounter.cs
│ │ ├── ByteArrayEqualityComparer.cs
│ │ ├── ByteArrayUtility.cs
│ │ ├── Clock.cs
│ │ ├── OpCode.cs
│ │ ├── Poller.cs
│ │ ├── PollerBase.cs
│ │ ├── Proactor.cs
│ │ ├── Signaler.cs
│ │ ├── SocketUtility.cs
│ │ ├── SpanUtility.cs
│ │ ├── StopSignaler.cs
│ │ ├── StringLib.cs
│ │ ├── Switch.cs
│ │ └── YQueue.cs
│ ├── YPipe.cs
│ ├── ZObject.cs
│ └── ZmqSocketOption.cs
├── DnsEndPoint.cs
├── EmptyArray.cs
├── Endianness.cs
├── ErrorCode.cs
├── EventDelegator.cs
├── GroupSocketExtensions.cs
├── INetMQPoller.cs
├── INetMQSocket.cs
├── IOutgoingSocket.cs
├── IReceivingSocket.cs
├── ISocketPollable.cs
├── ISocketPollableCollection.cs
├── InterfaceCollection.cs
├── MechanismType.cs
├── Monitoring
│ ├── NetMQMonitor.cs
│ └── NetMQMonitorEventArgs.cs
├── Msg.cs
├── NetMQ.csproj
├── NetMQ.snk
├── NetMQActor.cs
├── NetMQBeacon.cs
├── NetMQCertificate.cs
├── NetMQConfig.cs
├── NetMQException.cs
├── NetMQFrame.cs
├── NetMQMessage.cs
├── NetMQPoller.cs
├── NetMQProactor.cs
├── NetMQQueue.cs
├── NetMQRuntime.cs
├── NetMQSelector.cs
├── NetMQSocket.cs
├── NetMQSocketEventArgs.cs
├── NetMQSynchronizationContext.cs
├── NetMQTimer.cs
├── NetworkOrderBitsConverter.cs
├── OutgoingSocketExtensions.cs
├── PollEvents.cs
├── Properties
│ └── AssemblyInfo.cs
├── Proxy.cs
├── ReceiveThreadSafeSocketExtensions.cs
├── ReceivingSocketExtensions.cs
├── RoutingIdSocketExtensions.cs
├── RoutingKey.cs
├── SendReceiveConstants.cs
├── SendThreadSafeSocketExtensions.cs
├── SocketEvents.cs
├── SocketOptions.cs
├── Sockets
│ ├── ClientSocket.cs
│ ├── DealerSocket.cs
│ ├── DishSocket.cs
│ ├── GatherSocket.cs
│ ├── PairSocket.cs
│ ├── PeerSocket.cs
│ ├── PublisherSocket.cs
│ ├── PullSocket.cs
│ ├── PushSocket.cs
│ ├── RadioSocket.cs
│ ├── RequestSocket.cs
│ ├── ResponseSocket.cs
│ ├── RouterSocket.cs
│ ├── ScatterSocket.cs
│ ├── ServerSocket.cs
│ ├── StreamSocket.cs
│ ├── SubscriberSocket.cs
│ ├── XPublisherSocket.cs
│ └── XSubscriberSocket.cs
├── TaskThread.cs
├── ThreadSafeSocket.cs
├── ThreadSafeSocketExtensions.cs
├── ThreadSafeSocketOptions.cs
├── Utils
│ ├── ArrayExtensions.cs
│ ├── Assumes.cs
│ ├── EncodingExtensions.cs
│ └── Strings.cs
└── ZmqSocketType.cs
├── Performance
├── NetMQ.SimpleTests
│ ├── ITest.cs
│ ├── LatencyBenchmark.cs
│ ├── NetMQ.SimpleTests.csproj
│ ├── Program.cs
│ └── ThroughputBenchmark.cs
├── local_lat
│ ├── Program.cs
│ └── local_lat.csproj
├── local_thr
│ ├── Program.cs
│ ├── app.config
│ └── local_thr.csproj
├── remote_lat
│ ├── Program.cs
│ └── remote_lat.csproj
└── remote_thr
│ ├── Program.cs
│ ├── app.config
│ └── remote_thr.csproj
└── build.bat
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ### Environment
2 |
3 | NetMQ Version:
4 | Operating System:
5 | .NET Version:
6 |
7 | ### Expected behaviour
8 |
9 |
10 |
11 | ### Actual behaviour
12 |
13 |
14 |
15 | ### Steps to reproduce the behaviour
16 |
17 |
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Number of days of inactivity before an issue becomes stale
2 | daysUntilStale: 365
3 | # Number of days of inactivity before a stale issue is closed
4 | daysUntilClose: 56
5 | # Issues with these labels will never be considered stale
6 | exemptLabels:
7 | - "Help Request"
8 | - "Feature Request"
9 | - "Problem reproduced"
10 | - Critical
11 | # Label to use when marking an issue as stale
12 | staleLabel: stale
13 | # Comment to post when marking an issue as stale. Set to `false` to disable
14 | markComment: >
15 | This issue has been automatically marked as stale because it has not had
16 | activity for 365 days. It will be closed if no further activity occurs within
17 | 56 days. Thank you for your contributions.
18 | # Comment to post when closing a stale issue. Set to `false` to disable
19 | closeComment: false
20 |
--------------------------------------------------------------------------------
/.github/workflows/CI.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on: [push, pull_request]
3 |
4 | jobs:
5 | ununtu:
6 | runs-on: ubuntu-latest
7 | env:
8 | DOTNET_NOLOGO: true
9 | steps:
10 | - uses: actions/checkout@v4.2.2
11 | - uses: actions/setup-dotnet@v4.1.0
12 | with:
13 | dotnet-version: 9.0.x
14 | - run: dotnet restore src/NetMQ.sln
15 | - name: build
16 | run: dotnet build src/NetMQ.sln /p:Configuration=Release /verbosity:minimal
17 | - name: test net9.0
18 | run: dotnet test -v n -p:ParallelizeTestCollections=false --configuration Release --no-build -f net9.0 src/NetMQ.Tests/NetMQ.Tests.csproj
19 | windows:
20 | runs-on: windows-latest
21 | env:
22 | DOTNET_NOLOGO: true
23 | steps:
24 | - uses: actions/checkout@v4.2.2
25 | - uses: actions/setup-dotnet@v4.1.0
26 | with:
27 | dotnet-version: 9.0.x
28 | - name: Install codecov
29 | run: |
30 | choco install opencover.portable
31 | choco install codecov
32 | - run: dotnet restore src/NetMQ.sln
33 | - name: build
34 | run: dotnet build src/NetMQ.sln /p:Configuration=Release /verbosity:minimal
35 | - name: test net9.0
36 | run: dotnet test -v n -p:ParallelizeTestCollections=false --configuration Release --no-build -f net9.0 src\NetMQ.Tests\NetMQ.Tests.csproj
37 | - name: test net47
38 | run: dotnet test -v n -p:ParallelizeTestCollections=false --configuration Release --no-build -f net47 src\NetMQ.Tests\NetMQ.Tests.csproj
39 | - name: coverage
40 | run: |
41 | OpenCover.Console.exe -register:user -target:"C:\Program Files\dotnet\dotnet.exe" -targetargs:"test --no-build --configuration Release -f net6.0 --logger:trx;LogFileName=results.trx /p:DebugType=full src\NetMQ.Tests\NetMQ.Tests.csproj" -filter:"+[NetMQ*]* -[NetMQ.Tests*]*" -output:".\NetMQ_coverage.xml" -oldStyle
42 | codecov -f "NetMQ_coverage.xml"
43 |
--------------------------------------------------------------------------------
/.github/workflows/prerelease.yml:
--------------------------------------------------------------------------------
1 | name: prerelease
2 | on:
3 | release:
4 | types: [prereleased]
5 |
6 | jobs:
7 | windows:
8 | runs-on: windows-latest
9 | steps:
10 | - uses: actions/checkout@v3
11 | - name: Get the version
12 | id: get_version
13 | run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
14 | shell: bash
15 | - run: echo ${{ steps.get_version.outputs.VERSION }}
16 | - run: dotnet pack src/NetMQ/NetMQ.csproj -o . -c Release /p:PackageVersion="${{ steps.get_version.outputs.VERSION }}-pre" /p:Version=${{ steps.get_version.outputs.VERSION }} /p:ContinuousIntegrationBuild=true
17 | - run: dotnet nuget push *.nupkg -k $NUGET_API_KEY -s https://api.nuget.org/v3/index.json
18 | env:
19 | NUGET_API_KEY: ${{ secrets.NuGetAPIKey }}
20 | shell: bash
21 |
22 |
23 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: release
2 | on:
3 | release:
4 | types: [published]
5 |
6 | jobs:
7 | windows:
8 | runs-on: windows-latest
9 | if: "!github.event.release.prerelease"
10 | steps:
11 | - uses: actions/checkout@v3
12 | - name: Get the version
13 | id: get_version
14 | run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
15 | shell: bash
16 | - run: echo ${{ steps.get_version.outputs.VERSION }}
17 | - run: dotnet pack src/NetMQ/NetMQ.csproj -o . -c Release /p:PackageVersion=${{ steps.get_version.outputs.VERSION }} /p:Version=${{ steps.get_version.outputs.VERSION }} /p:ContinuousIntegrationBuild=true
18 | - run: dotnet nuget push *.nupkg -k $NUGET_API_KEY -s https://api.nuget.org/v3/index.json
19 | env:
20 | NUGET_API_KEY: ${{ secrets.NuGetAPIKey }}
21 | shell: bash
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore Windows thumbnails
2 | Thumbs.db
3 |
4 | # Ignore Visual Studio files
5 | *.obj
6 | *.exe
7 | *.pdb
8 | *.nupkg
9 | *.user
10 | *.aps
11 | *.pch
12 | *.vspscc
13 | *_i.c
14 | *_p.c
15 | *.ncb
16 | *.suo
17 | *.tlb
18 | *.tlh
19 | *.bak
20 | *.cache
21 | *.ilk
22 | *.log
23 | *.orig
24 | [Bb]in
25 | [Dd]ebug*/
26 | *.lib
27 | *.sbr
28 | obj/
29 | [Rr]elease*/
30 | _ReSharper*/
31 | *.DotSettings
32 | [Tt]est[Rr]esult*
33 |
34 | # Ignore MonoDevelop files
35 | *.userprefs
36 |
37 | # Ignore NUnit project files
38 | *.nunit
39 |
40 | # Ignore NuGet Packages
41 | /src/packages/
42 |
43 | #Ignore VS files
44 | .vs/
45 |
46 | #Ignore lock files
47 | *.lock.json
48 | .idea/
49 | /src/*.DotSettings
50 |
--------------------------------------------------------------------------------
/.readthedocs.yml:
--------------------------------------------------------------------------------
1 | # Read the Docs configuration file for MkDocs projects
2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
3 |
4 | # Required
5 | version: 2
6 |
7 | # Set the version of Python and other tools you might need
8 | build:
9 | os: ubuntu-22.04
10 | tools:
11 | python: "3.12"
12 |
13 | mkdocs:
14 | configuration: mkdocs.yml
15 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: csharp
2 | mono: none
3 | dotnet: 3.1
4 |
5 | addons:
6 | apt:
7 | packages:
8 | - dotnet-sdk-2.2
9 |
10 |
11 | script:
12 | - dotnet restore src/NetMQ.sln
13 | - dotnet build -v q -f netstandard2.0 src/NetMQ/NetMQ.csproj
14 | - dotnet test -v n --logger "Console;noprogress=true" -p:ParallelizeTestCollections=false -f netcoreapp2.1 --filter Category!=Beacon src/NetMQ.Tests/NetMQ.Tests.csproj -- RunConfiguration.ReporterSwitch=verbose
15 |
16 |
--------------------------------------------------------------------------------
/AUTHORS.md:
--------------------------------------------------------------------------------
1 | Contributors
2 | ===
3 |
4 | * Alexey Yakovlev — [@yallie](https://github.com/yallie)
5 | * Charlie Friedemann — [@charliebone](https://github.com/charliebone)
6 | * Christophe Juniet — [@cjuniet](https://github.com/cjuniet)
7 | * Dan de Zille — [@dandezille](https://github.com/dandezille)
8 | * Doron Somech — [@somdoron](https://github.com/somdoron)
9 | * Drew Noakes — [@drewnoakes](https://github.com/drewnoakes)
10 | * Eugen Dück — [@EugenDueck](https://github.com/EugenDueck)
11 | * Grant Birchmeier — [@gbirchmeier](https://github.com/gbirchmeier)
12 | * Ilya Loginov — [@iloginov](https://github.com/iloginov)
13 | * James Hurst — [@JamesWhurst](https://github.com/JamesWhurst)
14 | * Jay Shelton — [@jayshelton](https://github.com/jayshelton)
15 | * Miguel Angel Jimenez — [@majimenezp](https://github.com/majimenezp)
16 | * Nicolas Dextraze — [@ndextraze-pbp](https://github.com/ndextraze-pbp)
17 | * Peter H. Merkel — [@mph911](https://github.com/mph911)
18 | * Robert Horvick — [@bubbafat](https://github.com/bubbafat)
19 | * Sacha Barber — [@sachabarber](https://github.com/sachabarber)
20 | * Tobias Behr — [@tobi-tobsen](https://github.com/tobi-tobsen)
21 | * Tom Robinson — [@tjrobinson](https://github.com/tjrobinson)
22 | * Victor Baybekov — [@buybackoff](https://github.com/buybackoff)
23 | * Tobias Böhm — [@tobiasb](https://github.com/tobiasb)
24 | * Dale Brubaker — [@dalebrubaker](https://github.com/dalebrubaker)
25 | * Calin Pirtea — [@pcalin](https://github.com/pcalin)
26 | * Osiris Pedroso — [@opedroso](https://github.com/opedroso)
27 | * Mike Miller — [@mikepmiller](https://github.com/mikepmiller)
28 | * Miguel Labayen — [@milabtom](https://github.com/milabtom)
29 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ### Contributing to NetMQ
2 |
3 | * The contributors are listed in [AUTHORS.md](https://github.com/zeromq/netmq/blob/master/AUTHORS.md) (add yourself).
4 |
5 | * This project uses a modified version of the LGPL v3 license, see
6 | [COPYING.LESSER](https://github.com/zeromq/netmq/blob/master/COPYING.LESSER).
7 |
8 | * We use the [C4.1 (Collective Code Construction Contract)](http://rfc.zeromq.org/spec:22) process for contributions.
9 | Please read this if you are unfamiliar with it.
10 |
11 | * Please maintain the existing code style.
12 |
13 | * Please try to keep your commits small and focussed.
14 |
15 | * If the project diverges from your branch, please rebase instead of merging. This makes the commit graph easier to read.
16 |
--------------------------------------------------------------------------------
/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: 4.0.0.{build}
2 | skip_tags: true
3 | image: Visual Studio 2019
4 | configuration: Release
5 |
6 | before_build:
7 | - choco install opencover.portable
8 | - choco install codecov
9 |
10 | build_script:
11 | - dotnet restore src/NetMQ.sln
12 | - dotnet build src/NetMQ.sln /p:Configuration=Release /p:PackageVersion=%APPVEYOR_BUILD_VERSION%-pre /p:Version=%APPVEYOR_BUILD_VERSION% /p:ContinuousIntegrationBuild=true /verbosity:minimal
13 | - dotnet pack src/NetMQ/NetMQ.csproj -c Release --no-build /p:PackageVersion=%APPVEYOR_BUILD_VERSION%-pre /p:Version=%APPVEYOR_BUILD_VERSION%
14 |
15 | test_script:
16 | - dotnet test -v n -p:ParallelizeTestCollections=false --configuration Release --no-build -f netcoreapp2.1 src\NetMQ.Tests\NetMQ.Tests.csproj
17 | - dotnet test -v n -p:ParallelizeTestCollections=false --configuration Release --no-build -f net47 src\NetMQ.Tests\NetMQ.Tests.csproj
18 | - OpenCover.Console.exe -register:user -target:"C:\Program Files\dotnet\dotnet.exe" -targetargs:"test --no-build --configuration Release -f netcoreapp2.1 --logger:trx;LogFileName=results.trx /p:DebugType=full src\NetMQ.Tests\NetMQ.Tests.csproj" -filter:"+[NetMQ*]* -[NetMQ.Tests*]*" -output:".\NetMQ_coverage.xml" -oldStyle
19 | - codecov -f "NetMQ_coverage.xml"
20 |
21 | artifacts:
22 | - path: '**\*.nupkg'
23 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | coverage:
2 | range: 65..95
3 | status:
4 | project:
5 | default:
6 | target: auto
7 | threshold: 0.5%
8 | base: auto
9 |
10 | comment:
11 | require_changes: true
12 | layout: "diff, files"
13 |
--------------------------------------------------------------------------------
/docs/Images/ActorPass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/docs/Images/ActorPass.png
--------------------------------------------------------------------------------
/docs/Images/ActorTrad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/docs/Images/ActorTrad.png
--------------------------------------------------------------------------------
/docs/Images/ActorsOut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/docs/Images/ActorsOut.png
--------------------------------------------------------------------------------
/docs/Images/Fanout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/docs/Images/Fanout.png
--------------------------------------------------------------------------------
/docs/Images/NetMQLogo.svg:
--------------------------------------------------------------------------------
1 |
2 |
23 |
--------------------------------------------------------------------------------
/docs/Images/PgmSettingsInWindows.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/docs/Images/PgmSettingsInWindows.png
--------------------------------------------------------------------------------
/docs/Images/PubSubUsingTopics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/docs/Images/PubSubUsingTopics.png
--------------------------------------------------------------------------------
/docs/Images/RequestResponse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/docs/Images/RequestResponse.png
--------------------------------------------------------------------------------
/docs/Images/RequestResponse2Receives.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/docs/Images/RequestResponse2Receives.png
--------------------------------------------------------------------------------
/docs/Images/RequestResponse2Sends.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/docs/Images/RequestResponse2Sends.png
--------------------------------------------------------------------------------
/docs/Images/XPubXSubDemo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/docs/Images/XPubXSubDemo.png
--------------------------------------------------------------------------------
/docs/async-await.md:
--------------------------------------------------------------------------------
1 | Async Await
2 | ===========
3 |
4 | Since version (4.0.0.239-pre) NetMQ support async/await.
5 |
6 | To use async/await feature you need to create a `NetMQRuntime`.
7 |
8 | ## Example:
9 |
10 | ```csharp
11 | async Task ServerAsync()
12 | {
13 | using (var server = new RouterSocket("inproc://async"))
14 | {
15 | for (int i = 0; i < 1000; i++)
16 | {
17 | var (routingKey, more) = await server.ReceiveRoutingKeyAsync();
18 | var (message, _) = await server.ReceiveFrameStringAsync();
19 |
20 | // TODO: process message
21 |
22 | await Task.Delay(100);
23 | server.SendMoreFrame(routingKey);
24 | server.SendFrame("Welcome");
25 | }
26 | }
27 | }
28 |
29 | async Task ClientAsync()
30 | {
31 | using (var client = new DealerSocket("inproc://async"))
32 | {
33 | for (int i = 0; i < 1000; i++)
34 | {
35 | client.SendFrame("Hello");
36 | var (message, more) = await client.ReceiveFrameStringAsync();
37 |
38 | // TODO: process reply
39 |
40 | await Task.Delay(100);
41 | }
42 | }
43 | }
44 |
45 | static void Main(string[] args)
46 | {
47 | using (var runtime = new NetMQRuntime())
48 | {
49 | runtime.Run(ServerAsync(), ClientAsync());
50 | }
51 | }
52 | ```
53 |
54 | NetMQRuntime is a wrapper over NetMQPoller, when calling an async function the socket is automatically added to the internal poller.
55 | NetMQRuntime is also a NetMQScheduler and SyncrhonizationContext, so any awaited function is continuing on the runtime's thread.
56 |
57 | NetMQSocket should still be used only within one thread.
58 |
59 | `NetMQRuntime.Run` can accept multiple tasks and also a cancellation token.
60 | `NetMQRuntime.Run` runs until all tasks are completed or cancellation token has been cancelled.
61 |
--------------------------------------------------------------------------------
/docs/beacon.md:
--------------------------------------------------------------------------------
1 | Beacon
2 | ======
3 |
4 | `NetMQBeacon` implements a peer-to-peer discovery service for local networks.
5 |
6 | A beacon can broadcast and/or capture service announcements using UDP messages on the local area network.
7 | You can define the format of your outgoing beacons, and set a filter that validates incoming beacons.
8 | Beacons are sent and received asynchronously in the background.
9 |
10 | We can use the `NetMQBeacon` to discover and connect to other NetMQ/CZMQ services in the network automatically
11 | without central configuration. Please note that to use `NetMQBeacon` your infrastructure must support broadcast.
12 | Most cloud providers doesn't support broadcast.
13 |
14 | This implementation uses IPv4 UDP broadcasts, and is a port of [zbeacon from czmq](https://github.com/zeromq/czmq#toc4-425)
15 | with some extensions, though it maintains network compatibility.
16 |
17 | ## Example: Implementing a Bus
18 |
19 | `NetMQBeacon` can be used to create a simple bus that allows a set of nodes
20 | to discover one another, configured only via a shared port number.
21 |
22 | * Each bus node binds a subscriber socket and connects to other nodes with a publisher socket.
23 | * Each node will use `NetMQBeacon` to announce its existence and to discover other nodes. We will also use `NetMQActor` to implement our node.
24 |
25 | The source for sample project is available online at:
26 |
27 | * [https://github.com/NetMQ/Samples/blob/master/src/Beacon/BeaconDemo/Bus.cs](https://github.com/NetMQ/Samples/blob/master/src/Beacon/BeaconDemo/Bus.cs)
28 |
29 |
30 | ## Further reading
31 |
32 | * [Solving the Discovery Problem](http://hintjens.com/blog:32)
33 |
--------------------------------------------------------------------------------
/docs/cleanup.md:
--------------------------------------------------------------------------------
1 | Cleanup
2 | =======
3 |
4 | New with NetMQ version 4 we said goodbye to NetMQContext. We can now create sockets with the new operator without the NetMQContext.
5 | Though this makes using the library simpler, it also adds complication to cleaning it up.
6 |
7 | # Why does NetMQ need Cleanup?
8 |
9 | NetMQ creates a few background threads. Also, when you call Dispose on a Socket the process is asynchronous and actually happens in a background thread.
10 | Because NetMQ threads are background threads you can actually exit the application without a proper cleanup of the NetMQ library, though it is not recommeneded.
11 |
12 | When exiting AppDomain it might be more complicated, and you have to cleanup the NetMQ library.
13 |
14 | # What is Linger?
15 |
16 | Linger is the allowed time for the Socket to send all messages before getting disposed.
17 | So when we call Dispose on a Socket with Linger set to 1 second it might take up to 1 second to the socket to get diposed.
18 | In that time the library will try to send all the pending messages, if it finish before the linger the socket will get disposed before the time is up.
19 |
20 | As said all this is happening in the background, so if the linger is set but we are not properly cleaning-up the library the linger will get ingored.
21 | So if the linger is important for you, make sure you properly cleanup the library.
22 |
23 | With version 4 the default Linger of a socket is zero, it means that the library will not wait before disposing the socket.
24 | You can change the Linger for a Socket, but also change the default Linger for all Socket with NetMQConfig.Linger.
25 |
26 | # How to Cleanup?
27 |
28 | The most important thing to know about cleanup is that you must call Dispose on all sockets before calling Cleanup.
29 | Also make sure to cleanup any other resource from NetMQ library, like NetMQPoller, NetMQQueue and etc...
30 | If socket is not get disposed the NetMQConfig.Cleanup will block forever.
31 |
32 | Lastly you need to call the NetMQConfig.Cleanup. You can do that in the last line of the Main method:
33 |
34 | ``` csharp
35 | static void Main(string[] args)
36 | try
37 | {
38 | // Do you logic here
39 | }
40 | finally
41 | {
42 | NetMQConfig.Cleanup();
43 | }
44 | ```
45 |
46 | If you are lazy and don't care about cleaning the library you can also call NetMQConfig.Cleanup with the block parameter set to false.
47 | When set to false the cleanup will not wait for Sockets to Send all messages and will just kill the background threads.
48 |
49 | # Tests
50 |
51 | When using NetMQ within your tests you also need to make sure you Cleanup the library.
52 |
53 | I suggest to just add global tear down to your tests and then call NetMQConfig.Cleanup.
54 |
55 | This how to do it with NUnit:
56 |
57 | ``` csharp
58 | [SetUpFixture]
59 | public class Setup
60 | {
61 | [OneTimeTearDown]
62 | public void TearDown()
63 | {
64 | NetMQConfig.Cleanup(false);
65 | }
66 | }
67 | ```
68 |
69 | In tests it is important to call Cleanup with block set to false so in case of failing test the entire process is not hanging.
70 |
--------------------------------------------------------------------------------
/docs/devices.md:
--------------------------------------------------------------------------------
1 | Devices
2 | ===
3 |
4 | See:
5 |
6 | * http://api.zeromq.org/2-1:zmq-device
7 | * `IDevice` and `DeviceBase`
8 | * `ForwarderDevice`
9 | * `QueueDevice`
10 | * `StreamerDevice`
11 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | NetMQ is a 100% native C# port of ZeroMQ, a lightweight messaging library.
4 |
5 | NetMQ extends the standard socket interface with features traditionally provided by specialised messaging middleware products. NetMQ sockets provide an abstraction of asynchronous message queues, multiple messaging patterns, message filtering (subscriptions), seamless access to multiple transport protocols and more.
6 |
7 | ## Documentation
8 |
9 | NetMQ documentation is available at [netmq.readthedocs.org](http://netmq.readthedocs.org/en/latest/).
10 |
11 | Using NetMQ requires an understanding of ZeroMQ, for which there is no better documentation than the [ZeroMQ Guide](http://zguide.zeromq.org/page:all).
12 |
13 | ## Installation
14 |
15 | You can install NetMQ from [NuGet](https://nuget.org/packages/NetMQ/).
16 |
--------------------------------------------------------------------------------
/docs/proactor.md:
--------------------------------------------------------------------------------
1 | Proactor
2 | ========
3 |
4 | `NetMQProactor` quickly processes messages received on a socket using a dedicated thread.
5 |
6 | ``` csharp
7 | using (var receiveSocket = new DealerSocket(">tcp://localhost:5555"))
8 | using (var proactor = new NetMQProactor(receiveSocket,
9 | (socket, message) => ProcessMessage(message)))
10 | {
11 | // ...
12 | }
13 | ```
14 |
15 | Internally the proactor creates a `NetMQPoller` for the socket, and a `NetMQActor` to coordinate
16 | the poller thread and disposal.
17 |
--------------------------------------------------------------------------------
/docs/queue.md:
--------------------------------------------------------------------------------
1 | Queue
2 | ======
3 |
4 | `NetMQQueue` is a producer-consumer queue that supports multiple producers and a single consumer.
5 |
6 | You should add the queue to a `NetMQPoller`, and attach the consumer to its `ReceiveReady` event.
7 | Producers call `Enqueue(T)`.
8 |
9 | This class can eliminate boilerplate code associated with marshalling operations onto a single thread.
10 |
11 | ``` csharp
12 | using (var queue = new NetMQQueue())
13 | using (var poller = new NetMQPoller { queue })
14 | {
15 | queue.ReceiveReady += (sender, args) => ProcessCommand(queue.Dequeue());
16 | poller.RunAsync();
17 | // Then, from various threads...
18 | queue.Enqueue(new DoSomethingCommand());
19 | queue.Enqueue(new DoSomethingElseCommand());
20 | }
21 | ```
22 |
--------------------------------------------------------------------------------
/docs/scheduler.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/docs/scheduler.md
--------------------------------------------------------------------------------
/docs/stream.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/docs/stream.md
--------------------------------------------------------------------------------
/docs/timer.md:
--------------------------------------------------------------------------------
1 | Timer
2 | =====
3 |
4 | A `NetMQTimer` allows actions to be performed periodically. Timer instances may be added to a `NetMQPoller`, and their
5 | `Elapsed` event will fire according to the specified `Interval` and `Enabled` property values.
6 |
7 | The event is raised on the poller's thread.
8 |
9 | ``` csharp
10 | var timer = new NetMQTimer(TimeSpan.FromMilliseconds(100));
11 | timer.Elapsed += (sender, args) => { /* handle timer event */ };
12 | using (var poller = new NetMQPoller { timer })
13 | {
14 | poller.Run();
15 | }
16 | ```
17 |
--------------------------------------------------------------------------------
/img/NetMQ.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/img/NetMQ.ico
--------------------------------------------------------------------------------
/img/NetMQLogo-128px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/img/NetMQLogo-128px.png
--------------------------------------------------------------------------------
/img/NetMQLogo-32px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/img/NetMQLogo-32px.png
--------------------------------------------------------------------------------
/img/NetMQLogo-400px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/img/NetMQLogo-400px.png
--------------------------------------------------------------------------------
/img/NetMQLogo-48px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/img/NetMQLogo-48px.png
--------------------------------------------------------------------------------
/img/NetMQLogo-64px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/img/NetMQLogo-64px.png
--------------------------------------------------------------------------------
/img/NetMQLogo.svg:
--------------------------------------------------------------------------------
1 |
2 |
23 |
--------------------------------------------------------------------------------
/img/NetMQLogoSquare-256px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/img/NetMQLogoSquare-256px.png
--------------------------------------------------------------------------------
/img/NetMQLogoSquare-400px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/img/NetMQLogoSquare-400px.png
--------------------------------------------------------------------------------
/mkdocs.yml:
--------------------------------------------------------------------------------
1 | site_name: NetMQ
2 |
3 | pages:
4 | - Home: index.md
5 | - Introduction: introduction.md
6 | - Concepts:
7 | - Receiving and Sending: receiving-sending.md
8 | - Async/Await: async-await.md
9 | - Messages: message.md
10 | - Transports: transports.md
11 | - Cleanup: cleanup.md
12 | - Components:
13 | - Poller: poller.md
14 | - Actor: actor.md
15 | - Beacon: beacon.md
16 | - Timer: timer.md
17 | - Queue: queue.md
18 | - Proactor: proactor.md
19 | - Patterns:
20 | - Request-Response: request-response.md
21 | - Pub-Sub: pub-sub.md
22 | - Push-Pull: push-pull.md
23 | - Router-Dealer: router-dealer.md
24 | - XSub-XPub: xpub-xsub.md
25 |
26 | theme: readthedocs
27 | repo_url: https://github.com/zeromq/netmq/
28 | markdown_extensions: [codehilite]
29 |
--------------------------------------------------------------------------------
/src/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 10
5 | enable
6 | true
7 | true
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $([System.IO.Path]::Combine('$(IntermediateOutputPath)','$(TargetFrameworkMoniker).AssemblyAttributes$(DefaultLanguageSourceExtension)'))
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/NetMQ.Tests/ActorTests.cs:
--------------------------------------------------------------------------------
1 | using NetMQ.Sockets;
2 | using Xunit;
3 |
4 | namespace NetMQ.Tests
5 | {
6 | public class ActorTests : IClassFixture
7 | {
8 | public ActorTests() => NetMQConfig.Cleanup();
9 |
10 | [Fact]
11 | public void Simple()
12 | {
13 | void ShimAction(PairSocket shim)
14 | {
15 | shim.SignalOK();
16 |
17 | while (true)
18 | {
19 | var msg = shim.ReceiveMultipartMessage();
20 | var command = msg[0].ConvertToString();
21 |
22 | if (command == NetMQActor.EndShimMessage)
23 | break;
24 |
25 | if (command == "Hello")
26 | {
27 | Assert.Equal(2, msg.FrameCount);
28 | Assert.Equal("Hello", msg[1].ConvertToString());
29 | shim.SendFrame("World");
30 | }
31 | }
32 | }
33 |
34 | using (var actor = NetMQActor.Create(ShimAction))
35 | {
36 | actor.SendMoreFrame("Hello").SendFrame("Hello");
37 |
38 | Assert.Equal("World", actor.ReceiveFrameString());
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/NetMQ.Tests/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/NetMQ.Tests/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using Xunit;
2 |
3 | [assembly: CollectionBehavior(DisableTestParallelization = true)]
4 |
--------------------------------------------------------------------------------
/src/NetMQ.Tests/CleanupAfterFixture.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using JetBrains.Annotations;
3 |
4 | namespace NetMQ.Tests
5 | {
6 | [UsedImplicitly]
7 | public sealed class CleanupAfterFixture : IDisposable
8 | {
9 | public void Dispose() => NetMQConfig.Cleanup();
10 | }
11 | }
--------------------------------------------------------------------------------
/src/NetMQ.Tests/CleanupTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using NetMQ.Sockets;
4 | using Xunit;
5 |
6 | namespace NetMQ.Tests
7 | {
8 | public class CleanupTests : IClassFixture
9 | {
10 | public CleanupTests() => NetMQConfig.Cleanup();
11 |
12 | [Fact(Skip = "Failing occasionally")]
13 | public void Block()
14 | {
15 | const int count = 1000;
16 |
17 | NetMQConfig.Linger = TimeSpan.FromSeconds(0.5);
18 |
19 | using (var client = new DealerSocket(">tcp://localhost:5557"))
20 | {
21 | // Sending a lot of messages
22 | client.Options.SendHighWatermark = count;
23 |
24 | for (int i = 0; i < count; i++)
25 | client.SendFrame("Hello");
26 | }
27 |
28 | var stopwatch = Stopwatch.StartNew();
29 |
30 | NetMQConfig.Cleanup(block: true);
31 |
32 | Assert.True(stopwatch.ElapsedMilliseconds > 500);
33 | }
34 |
35 | [Fact]
36 | public void NoBlock()
37 | {
38 | const int count = 1000;
39 |
40 | NetMQConfig.Linger = TimeSpan.FromSeconds(0.5);
41 |
42 | using (var client = new DealerSocket(">tcp://localhost:5557"))
43 | {
44 | // Sending a lot of messages
45 | client.Options.SendHighWatermark = count;
46 |
47 | for (int i = 0; i < count; i++)
48 | client.SendFrame("Hello");
49 | }
50 |
51 | var stopwatch = Stopwatch.StartNew();
52 |
53 | NetMQConfig.Cleanup(block: false);
54 |
55 | Assert.True(stopwatch.ElapsedMilliseconds < 500);
56 | }
57 |
58 | [Fact]
59 | public void NoBlockNoDispose()
60 | {
61 | new DealerSocket(">tcp://localhost:5557");
62 |
63 | NetMQConfig.Cleanup(block: false);
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/NetMQ.Tests/EventDelegatorTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xunit;
3 |
4 | namespace NetMQ.Tests
5 | {
6 | public class EventDelegatorTests
7 | {
8 | private class Args : EventArgs
9 | {
10 | public Args(T value) => Value = value;
11 | public T Value { get; }
12 | }
13 |
14 | private event EventHandler>? Source;
15 |
16 | [Fact]
17 | public void Basics()
18 | {
19 | EventHandler>? sourceHandler = null;
20 |
21 | var delegator = new EventDelegator>(
22 | () => Source += sourceHandler,
23 | () => Source -= sourceHandler);
24 |
25 | sourceHandler = (sender, args) => delegator.Fire(this, new Args(args.Value / 2.0));
26 |
27 | Assert.Null(Source);
28 |
29 | var value = 0.0;
30 | var callCount = 0;
31 |
32 | void DelegatorHandler(object? sender, Args args)
33 | {
34 | value = args.Value;
35 | callCount++;
36 | }
37 |
38 | delegator.Event += DelegatorHandler;
39 |
40 | Assert.NotNull(Source);
41 | Assumes.NotNull(Source);
42 |
43 | Assert.Equal(0, callCount);
44 |
45 | Source(this, new Args(5));
46 | Assert.Equal(2.5, value);
47 | Assert.Equal(1, callCount);
48 |
49 | Source(this, new Args(12));
50 | Assert.Equal(6.0, value);
51 | Assert.Equal(2, callCount);
52 |
53 | delegator.Event -= DelegatorHandler;
54 |
55 | Assert.Null(Source);
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/src/NetMQ.Tests/InProcActors/AccountJSON/Account.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace NetMQ.Tests.InProcActors.AccountJSON
3 | {
4 | public class Account
5 | {
6 | public Account(int id, string name, string sortCode, decimal balance)
7 | {
8 | Id = id;
9 | Name = name;
10 | SortCode = sortCode;
11 | Balance = balance;
12 | }
13 |
14 | public int Id { get; set; }
15 | public string Name { get; set; }
16 | public string SortCode { get; set; }
17 | public decimal Balance { get; set; }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/NetMQ.Tests/InProcActors/AccountJSON/AccountAction.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ.Tests.InProcActors.AccountJSON
2 | {
3 | ///
4 | /// This enum-type indicates the type of payment-card to be used in a transaction,
5 | /// either Debit or Credit.
6 | ///
7 | public enum TransactionType
8 | {
9 | Debit = 1,
10 | Credit = 2
11 | }
12 |
13 | ///
14 | /// An AccountAction represents a payment - providing an Amount and the type of payment-card.
15 | ///
16 | public class AccountAction
17 | {
18 | ///
19 | /// Create a new AccountAction object with a default TransactionType of Debit, and Amount of 0.
20 | ///
21 | public AccountAction()
22 | {}
23 |
24 | ///
25 | /// Create a new AccountAction object with the given TransactionType and Amount.
26 | ///
27 | /// either Debit or Credit
28 | /// the amount of the transaction (units of currency)
29 | public AccountAction(TransactionType transactionType, decimal amount)
30 | {
31 | TransactionType = transactionType;
32 | Amount = amount;
33 | }
34 |
35 | ///
36 | /// Get or set the type of payment-card to be used,
37 | /// which is either TransactionType.Debit or TransactionType.Credit.
38 | ///
39 | public TransactionType TransactionType { get; set; }
40 |
41 | ///
42 | /// Get or set the amount of this transaction (units of currency).
43 | ///
44 | public decimal Amount { get; set; }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/NetMQ.Tests/InProcActors/AccountJSON/AccountActorTests.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using Xunit;
3 |
4 | namespace NetMQ.Tests.InProcActors.AccountJSON
5 | {
6 | public class AccountActorTests
7 | {
8 | [Fact]
9 | public void AccountActorJsonSendReceiveTests()
10 | {
11 | var account = new Account(1, "Test Account", "11223", 0);
12 | var accountAction = new AccountAction(TransactionType.Credit, 10);
13 |
14 | using (var actor = NetMQActor.Create(new AccountShimHandler()))
15 | {
16 | actor.SendMoreFrame("AMEND ACCOUNT");
17 | actor.SendMoreFrame(JsonConvert.SerializeObject(accountAction));
18 | actor.SendFrame(JsonConvert.SerializeObject(account));
19 |
20 | var updatedAccount = JsonConvert.DeserializeObject(actor.ReceiveFrameString());
21 |
22 | Assert.NotNull(updatedAccount);
23 |
24 | Assert.Equal(10.0m, updatedAccount.Balance);
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/NetMQ.Tests/InProcActors/Echo/EchoActorTests.cs:
--------------------------------------------------------------------------------
1 | using Xunit;
2 |
3 | namespace NetMQ.Tests.InProcActors.Echo
4 | {
5 | public class EchoActorTests
6 | {
7 | [Theory]
8 | [InlineData("I like NetMQ")]
9 | [InlineData("NetMQ Is quite awesome")]
10 | [InlineData("Agreed sockets on steroids with isotopes")]
11 | public void EchoActorSendReceiveTests(string actorMessage)
12 | {
13 | using (var actor = NetMQActor.Create(new EchoShimHandler()))
14 | {
15 | actor.SendMoreFrame("ECHO");
16 | actor.SendFrame(actorMessage);
17 |
18 | Assert.Equal(
19 | $"ECHO BACK : {actorMessage}",
20 | actor.ReceiveFrameString());
21 | }
22 | }
23 |
24 | [Theory]
25 | [InlineData("BadCommand1")]
26 | public void BadCommandTests(string command)
27 | {
28 | const string actorMessage = "whatever";
29 |
30 | using (var actor = NetMQActor.Create(new EchoShimHandler()))
31 | {
32 | actor.SendMoreFrame(command);
33 | actor.SendFrame(actorMessage);
34 |
35 | Assert.Equal("Error: invalid message to actor", actor.ReceiveFrameString());
36 | }
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/NetMQ.Tests/InProcActors/Echo/EchoShimHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using NetMQ.Sockets;
3 |
4 | namespace NetMQ.Tests.InProcActors.Echo
5 | {
6 | ///
7 | /// This handler class illustrates a specific implementation that you would need
8 | /// to implement per actor. This essentially contains your commands/protocol
9 | /// and should deal with any command workload, as well as sending back to the
10 | /// other end of the PairSocket which calling code would receive by using the
11 | /// Actor classes' various ReceiveXXX() methods
12 | ///
13 | /// This is a VERY simple protocol. It just demonstrates what you would need
14 | /// to do to implement your own Shim handler.
15 | ///
16 | /// The only things you MUST do are
17 | ///
18 | /// 1. Bad commands should always send the following message
19 | /// "Error: invalid message to actor"
20 | /// 2. When we receive a command from the actor telling us to exit the pipeline we should immediately
21 | /// break out of the while loop, and dispose of the shim socket.
22 | /// 3. When an Exception occurs you should send that down the wire to Actors' calling code.
23 | ///
24 | public class EchoShimHandler : IShimHandler
25 | {
26 | public void Run(PairSocket shim)
27 | {
28 | shim.SignalOK();
29 |
30 | while (true)
31 | {
32 | try
33 | {
34 | //Message for this actor/shim handler is expected to be
35 | //Frame[0] : Command
36 | //Frame[1] : Payload
37 | //
38 | //Result back to actor is a simple echoing of the Payload, where
39 | //the payload is prefixed with "ECHO BACK "
40 | NetMQMessage msg = shim.ReceiveMultipartMessage();
41 |
42 | string command = msg[0].ConvertToString();
43 |
44 | switch (command)
45 | {
46 | case NetMQActor.EndShimMessage:
47 | return;
48 | case "ECHO":
49 | shim.SendFrame($"ECHO BACK : {msg[1].ConvertToString()}");
50 | break;
51 | default:
52 | shim.SendFrame("Error: invalid message to actor");
53 | break;
54 | }
55 | }
56 | // You WILL need to decide what Exceptions should be caught here, this is for
57 | // demonstration purposes only, any unhandled fault will bubble up to caller's code
58 | catch (Exception e)
59 | {
60 | shim.SendFrame($"Error: Exception occurred {e.Message}");
61 | }
62 | }
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/NetMQ.Tests/InProcActors/ExceptionShimExample/ExceptionShimActorTests.cs:
--------------------------------------------------------------------------------
1 | using Xunit;
2 |
3 | namespace NetMQ.Tests.InProcActors.ExceptionShimExample
4 | {
5 | public class ExceptionShimActorTests
6 | {
7 | [Fact]
8 | public void ShimExceptionTest()
9 | {
10 | using (var actor = NetMQActor.Create(new ExceptionShimHandler()))
11 | {
12 | actor.SendMoreFrame("SOME_COMMAND");
13 | actor.SendFrame("Whatever");
14 |
15 | Assert.Equal(
16 | "Error: Exception occurred Actors Shim threw an Exception",
17 | actor.ReceiveFrameString());
18 | }
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/NetMQ.Tests/InProcActors/ExceptionShimExample/ExceptionShimHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using NetMQ.Sockets;
3 |
4 | namespace NetMQ.Tests.InProcActors.ExceptionShimExample
5 | {
6 | ///
7 | /// This hander class is specific implementation that you would need
8 | /// to implement per actor. This essentially contains your commands/protocol
9 | /// and should deal with any command workload, as well as sending back to the
10 | /// other end of the PairSocket which calling code would receive by using the
11 | /// Actor classes various ReceiveXXX() methods
12 | ///
13 | /// This is a VERY simple protocol but it just demonstrates what you would need
14 | /// to do to implement your own Shim handler
15 | ///
16 | /// The only things you MUST do is to follow this example for handling
17 | /// a few things
18 | ///
19 | /// 1. Bad commands should always send the following message
20 | /// "Error: invalid message to actor"
21 | /// 2. When we receive a command from the actor telling us to exit the pipeline we should immediately
22 | /// break out of the while loop, and dispose of the shim socket
23 | /// 3. When an Exception occurs you should send that down the wire to Actors calling code
24 | ///
25 | public class ExceptionShimHandler : IShimHandler
26 | {
27 | public void Run(PairSocket shim)
28 | {
29 | shim.SignalOK();
30 |
31 | while (true)
32 | {
33 | try
34 | {
35 | NetMQMessage msg = shim.ReceiveMultipartMessage();
36 |
37 | string command = msg[0].ConvertToString();
38 |
39 | if (command == NetMQActor.EndShimMessage)
40 | break;
41 |
42 | //Simulate a failure that should be sent back to Actor
43 | throw new InvalidOperationException("Actors Shim threw an Exception");
44 | }
45 | //You WILL need to decide what Exceptions should be caught here, this is for
46 | //demonstration purposes only, any unhandled fault will bubble up to caller's code
47 | catch (InvalidOperationException e)
48 | {
49 | shim.SendFrame($"Error: Exception occurred {e.Message}");
50 | }
51 | }
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/NetMQ.Tests/MechanismTests.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 | using NetMQ.Core.Mechanisms;
3 | using Xunit;
4 |
5 | namespace NetMQ.Tests
6 | {
7 | public class MechanismTests
8 | {
9 | private Msg CreateMsg(string data, int lengthDiff)
10 | {
11 | Assert.NotNull(data);
12 | Assert.True(data.Length > 1);
13 | var length = data.Length + lengthDiff;
14 | Assert.True(length > 0);
15 | Assert.True(length < byte.MaxValue - 1);
16 |
17 | var msg = new Msg();
18 | msg.InitGC(new byte[data.Length + 1], 0, data.Length + 1);
19 | msg.SetFlags(MsgFlags.Command);
20 | msg.Put((byte)length);
21 | msg.Put(Encoding.ASCII, data, 1);
22 | return msg;
23 | }
24 |
25 | [Fact]
26 | public void IsCommandShouldReturnTrueForValidCommand()
27 | {
28 | var mechanism = new NullMechanism(null!, null!);
29 | var msg = CreateMsg("READY", 0);
30 | Assert.True(mechanism.IsCommand("READY", ref msg));
31 | }
32 |
33 | [Fact]
34 | public void IsCommandShouldReturnFalseForInvalidCommand()
35 | {
36 | var mechanism = new NullMechanism(null!, null!);
37 | var msg = CreateMsg("READY", -1);
38 | Assert.False(mechanism.IsCommand("READY", ref msg));
39 | msg = CreateMsg("READY", 1);
40 | Assert.False(mechanism.IsCommand("READY", ref msg));
41 | // this test case would fail due to an exception being throw (in 4.0.1.10 and prior)
42 | msg = CreateMsg("READY", 2);
43 | Assert.False(mechanism.IsCommand("READY", ref msg));
44 | }
45 |
46 | // this test was used to validate the behavior prior to changing the validation logic in Mechanism.IsCommand
47 | // [Fact]
48 | // public void IsCommandShouldThrowWhenLengthByteExceedsSize()
49 | // {
50 | // var mechanism = new NullMechanism(null, null);
51 | // var msg = CreateMsg("READY", 2);
52 | // Assert.Throws(() => mechanism.IsCommand("READY", ref msg));
53 | // }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/NetMQ.Tests/MockBufferPool.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace NetMQ.Tests
5 | {
6 |
7 | public sealed class MockBufferPool : IBufferPool
8 | {
9 | public int TakeCallCount { get; private set; }
10 | public List TakeSize { get; }
11 |
12 | public int ReturnCallCount { get; private set; }
13 | public List ReturnBuffer { get; }
14 |
15 | public MockBufferPool()
16 | {
17 | TakeSize = new List();
18 | ReturnBuffer = new List();
19 | }
20 |
21 | public void Reset()
22 | {
23 | TakeCallCount = 0;
24 | TakeSize.Clear();
25 |
26 | ReturnCallCount = 0;
27 | ReturnBuffer.Clear();
28 | }
29 |
30 | public byte[] Take(int size)
31 | {
32 | TakeCallCount++;
33 | TakeSize.Add(size);
34 |
35 | return new byte[size];
36 | }
37 |
38 | public void Return(byte[] buffer)
39 | {
40 | ReturnCallCount++;
41 | ReturnBuffer.Add(buffer);
42 | }
43 |
44 | void IDisposable.Dispose()
45 | {
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/src/NetMQ.Tests/MockCounterPool.cs:
--------------------------------------------------------------------------------
1 | using NetMQ.Core.Utils;
2 | using System;
3 |
4 | namespace NetMQ.Tests
5 | {
6 | public sealed class MockCounterPool : IAtomicCounterPool
7 | {
8 | public int TakeCallCount { get; private set; }
9 | public int ReturnCallCount { get; private set; }
10 |
11 | public MockCounterPool()
12 | {
13 |
14 | }
15 |
16 | public void Reset()
17 | {
18 | TakeCallCount = 0;
19 | ReturnCallCount = 0;
20 | }
21 |
22 | public AtomicCounter Take()
23 | {
24 | TakeCallCount++;
25 | return new AtomicCounter();
26 | }
27 |
28 | public void Return(AtomicCounter counter)
29 | {
30 | ReturnCallCount++;
31 | }
32 |
33 | void IDisposable.Dispose()
34 | {
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/src/NetMQ.Tests/NetMQ.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | portable
5 | ../NetMQ/NetMQ.snk
6 | true
7 | true
8 | true
9 | true
10 | net9.0;net47
11 |
12 |
13 |
14 |
15 |
16 | true
17 |
18 |
19 | /Library/Frameworks/Mono.framework/Versions/Current/lib/mono
20 | /usr/lib/mono
21 | /usr/local/lib/mono
22 |
23 | $(BaseFrameworkPathOverrideForMono)/4.7-api
24 |
25 |
26 | $(FrameworkPathOverride)/Facades;$(AssemblySearchPaths)
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/src/NetMQ.Tests/NetMQCertificateTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xunit;
3 |
4 | namespace NetMQ.Tests
5 | {
6 | public class NetMQCertificateTest : IClassFixture
7 | {
8 | public NetMQCertificateTest() => NetMQConfig.Cleanup();
9 |
10 | [Fact]
11 | public void X85()
12 | {
13 | for (int i = 0; i < 1000; i++)
14 | {
15 | var key = new NetMQCertificate();
16 | var copy = new NetMQCertificate(key.SecretKeyZ85!, key.PublicKeyZ85);
17 |
18 | Assert.Equal(key.SecretKeyZ85, copy.SecretKeyZ85);
19 | Assert.Equal(key.PublicKeyZ85, copy.PublicKeyZ85);
20 |
21 | Assert.Equal(key.SecretKey, copy.SecretKey);
22 | Assert.Equal(key.PublicKey, copy.PublicKey);
23 | }
24 | }
25 |
26 | [Fact]
27 | public void FromPublicKey()
28 | {
29 | var key = new NetMQCertificate();
30 | var copy = NetMQCertificate.FromPublicKey(key.PublicKeyZ85);
31 |
32 | Assert.Null(copy.SecretKeyZ85);
33 | Assert.Equal(key.PublicKeyZ85, copy.PublicKeyZ85);
34 |
35 | Assert.Null(copy.SecretKey);
36 | Assert.Equal(key.PublicKey, copy.PublicKey);
37 | }
38 |
39 | [Fact]
40 | public void FromSecretKey()
41 | {
42 | var key = new NetMQCertificate();
43 | var copy = new NetMQCertificate().FromSecretKey(key.SecretKeyZ85!);
44 |
45 | Assert.Equal(key.SecretKeyZ85, copy.SecretKeyZ85);
46 | Assert.Equal(key.PublicKeyZ85, copy.PublicKeyZ85);
47 |
48 | Assert.Equal(key.SecretKey, copy.SecretKey);
49 | Assert.Equal(key.PublicKey, copy.PublicKey);
50 | }
51 |
52 | [Fact]
53 | public void InvalidKeyLength()
54 | {
55 | Assert.Throws(() => new NetMQCertificate("hkszCq4i}RDe:TLT?", "hhRj/hiV-5CE(W!TLjLA%fGuxYmz9g}OZpJt2]cL"));
56 | Assert.Throws(() => new NetMQCertificate("hkszCq4i}RDe:TLT?)", "hhRj/hiV-5CE(W!TLjLA%fGuxYmz9g}OZpJt2]c"));
57 | }
58 |
59 | [Fact]
60 | public void InvalidKeyCharacter()
61 | {
62 | Assert.Throws(() => new NetMQCertificate(" kszCq4i}RDe:TLT?)", "hhRj/hiV-5CE(W!TLjLA%fGuxYmz9g}OZpJt2]cL"));
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/NetMQ.Tests/NetMQProactorTests.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using NetMQ.Sockets;
3 | using Xunit;
4 |
5 | namespace NetMQ.Tests
6 | {
7 | public class NetMQProactorTests : IClassFixture
8 | {
9 | public NetMQProactorTests() => NetMQConfig.Cleanup();
10 |
11 | [Fact]
12 | public void ReceiveMessage()
13 | {
14 | using (var server = new DealerSocket("@tcp://127.0.0.1:5555"))
15 | using (var client = new DealerSocket(">tcp://127.0.0.1:5555"))
16 | using (var manualResetEvent = new ManualResetEvent(false))
17 | using (new NetMQProactor(client, (socket, message) =>
18 | {
19 | manualResetEvent.Set();
20 | Assert.Same(client, socket);
21 | }))
22 | {
23 | server.SendFrame("Hello");
24 |
25 | Assert.True(manualResetEvent.WaitOne(100));
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/NetMQ.Tests/NetMQQueueTests.cs:
--------------------------------------------------------------------------------
1 | #if !NET35
2 | using System;
3 | using System.Net.Sockets;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using NetMQ.Sockets;
7 | using Xunit;
8 |
9 | namespace NetMQ.Tests
10 | {
11 | public class NetMQQueueTests : IClassFixture
12 | {
13 | public NetMQQueueTests() => NetMQConfig.Cleanup();
14 |
15 | [Fact]
16 | public void EnqueueDequeue()
17 | {
18 | using (var queue = new NetMQQueue())
19 | {
20 | queue.Enqueue(1);
21 |
22 | Assert.Equal(1, queue.Dequeue());
23 | }
24 | }
25 |
26 | [Fact]
27 | public void EnqueueShouldNotBlockWhenCapacityIsZero()
28 | {
29 | using (var mockSocket = new PairSocket())
30 | using (var queue = new NetMQQueue())
31 | {
32 | int socketWatermarkCapacity = mockSocket.Options.SendHighWatermark + mockSocket.Options.ReceiveHighWatermark;
33 |
34 | Task task = Task.Run(() =>
35 | {
36 | for (int i = 0; i < socketWatermarkCapacity + 100; i++)
37 | {
38 | queue.Enqueue(i);
39 | }
40 | });
41 |
42 | bool completed = task.Wait(TimeSpan.FromSeconds(1));
43 | Assert.True(completed, "Enqueue task should have completed " + socketWatermarkCapacity + " enqueue within 1 second");
44 | }
45 | }
46 |
47 | [Fact]
48 | public void TryDequeue()
49 | {
50 | using (var queue = new NetMQQueue())
51 | {
52 | Assert.False(queue.TryDequeue(out int result, TimeSpan.FromMilliseconds(100)));
53 |
54 | queue.Enqueue(1);
55 |
56 | Assert.True(queue.TryDequeue(out result, TimeSpan.FromMilliseconds(100)));
57 | Assert.Equal(1, result);
58 | }
59 | }
60 |
61 | [Fact]
62 | public void WithPoller()
63 | {
64 | using (var queue = new NetMQQueue())
65 | using (var poller = new NetMQPoller { queue })
66 | {
67 | var manualResetEvent = new ManualResetEvent(false);
68 |
69 | queue.ReceiveReady += (sender, args) =>
70 | {
71 | Assert.Equal(1, queue.Dequeue());
72 | manualResetEvent.Set();
73 | };
74 |
75 | poller.RunAsync();
76 |
77 | Assert.False(manualResetEvent.WaitOne(100));
78 | queue.Enqueue(1);
79 | Assert.True(manualResetEvent.WaitOne(100));
80 | }
81 | }
82 | }
83 | }
84 | #endif
85 |
--------------------------------------------------------------------------------
/src/NetMQ.Tests/NetworkOrderBitsConverterTests.cs:
--------------------------------------------------------------------------------
1 | using Xunit;
2 |
3 | namespace NetMQ.Tests
4 | {
5 | public class NetworkOrderBitsConverterTests
6 | {
7 | [Fact]
8 | public void TestInt64()
9 | {
10 | unchecked
11 | {
12 | RoundTripInt64(0x0102030405060708, 1, 2, 3, 4, 5, 6, 7, 8);
13 | RoundTripInt64((long)0xFFEEDDCCBBAA9988, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88);
14 | }
15 | }
16 |
17 | private static void RoundTripInt64(long num, params byte[] bytes)
18 | {
19 | byte[] buffer = NetworkOrderBitsConverter.GetBytes(num);
20 |
21 | Assert.Equal(8, buffer.Length);
22 | Assert.Equal(bytes, buffer);
23 |
24 | Assert.Equal(num, NetworkOrderBitsConverter.ToInt64(buffer));
25 |
26 | NetworkOrderBitsConverter.PutInt64(num, buffer);
27 |
28 | Assert.Equal(bytes, buffer);
29 |
30 | Assert.Equal(num, NetworkOrderBitsConverter.ToInt64(buffer));
31 | }
32 |
33 | [Fact]
34 | public void TestInt32()
35 | {
36 | unchecked
37 | {
38 | RoundTripInt32(0x01020304, 1, 2, 3, 4);
39 | RoundTripInt32((int)0xFFEEDDCC, 0xFF, 0xEE, 0xDD, 0xCC);
40 | }
41 | }
42 |
43 | private static void RoundTripInt32(int num, params byte[] bytes)
44 | {
45 | byte[] buffer = NetworkOrderBitsConverter.GetBytes(num);
46 |
47 | Assert.Equal(4, buffer.Length);
48 | Assert.Equal(bytes, buffer);
49 |
50 | Assert.Equal(num, NetworkOrderBitsConverter.ToInt32(buffer));
51 |
52 | NetworkOrderBitsConverter.PutInt32(num, buffer);
53 |
54 | Assert.Equal(bytes, buffer);
55 |
56 | Assert.Equal(num, NetworkOrderBitsConverter.ToInt32(buffer));
57 | }
58 |
59 | [Fact]
60 | public void TestInt16()
61 | {
62 | unchecked
63 | {
64 | RoundTripInt16(0x0102, 1, 2);
65 | RoundTripInt16((short)0xFFEE, 0xFF, 0xEE);
66 | }
67 | }
68 |
69 | private static void RoundTripInt16(short num, params byte[] bytes)
70 | {
71 | byte[] buffer = NetworkOrderBitsConverter.GetBytes(num);
72 |
73 | Assert.Equal(2, buffer.Length);
74 | Assert.Equal(bytes, buffer);
75 |
76 | Assert.Equal(num, NetworkOrderBitsConverter.ToInt16(buffer));
77 |
78 | NetworkOrderBitsConverter.PutInt16(num, buffer);
79 |
80 | Assert.Equal(bytes, buffer);
81 |
82 | Assert.Equal(num, NetworkOrderBitsConverter.ToInt16(buffer));
83 | }
84 |
85 | // [Fact]
86 | // public void PutInt64Perf()
87 | // {
88 | // for (var j = 0; j < 10; j++)
89 | // {
90 | // var buffer = new byte[8];
91 | // const int loopCount = 1000*1000*100;
92 | // var sw = Stopwatch.StartNew();
93 | // for (var k = 0; k < loopCount; k++)
94 | // NetworkOrderBitsConverter.PutInt64(0x12345678ABCDEF12L, buffer);
95 | // }
96 | // }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/NetMQ.Tests/PeerTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xunit;
3 | using System.Text;
4 | using System.Threading;
5 | using NetMQ.Sockets;
6 |
7 | namespace NetMQ.Tests
8 | {
9 | public class PeerTests : IClassFixture
10 | {
11 | [Fact]
12 | public void SendReceive()
13 | {
14 | using (var peer1 = new PeerSocket("@inproc://peertopeer"))
15 | using (var peer2 = new PeerSocket())
16 | {
17 | var peer1Identity = peer2.ConnectPeer("inproc://peertopeer");
18 |
19 | peer2.SendMoreFrame(peer1Identity);
20 | peer2.SendFrame("Hello");
21 |
22 | // peer2 identity
23 | var peer2Identity = peer1.ReceiveFrameBytes();
24 | var msg = peer1.ReceiveFrameString();
25 |
26 | Assert.Equal("Hello",msg);
27 |
28 | peer1.SendMoreFrame(peer2Identity);
29 | peer1.SendFrame("World");
30 |
31 | peer2.ReceiveFrameBytes();
32 | msg = peer2.ReceiveFrameString();
33 |
34 | Assert.Equal("World", msg);
35 |
36 | peer1.SendMoreFrame(peer2Identity);
37 | peer1.SendFrame("World2");
38 |
39 | peer2.ReceiveFrameBytes();
40 | msg = peer2.ReceiveFrameString();
41 |
42 | Assert.Equal("World2", msg);
43 | }
44 | }
45 |
46 | [Fact]
47 | public void CanSendAfterUnreachableException()
48 | {
49 | using (var peer1 = new PeerSocket())
50 | {
51 | var wrongKey = new byte[] { 0, 0, 0, 0 };
52 |
53 | Assert.Throws(() => peer1.SendMoreFrame(wrongKey));
54 |
55 | using (var peer2 = new PeerSocket("@inproc://peertopeer"))
56 | {
57 | var peer2Identity = peer1.ConnectPeer("inproc://peertopeer");
58 |
59 | peer1.SendMoreFrame(peer2Identity);
60 | peer1.SendFrame("Hello");
61 |
62 | peer2.ReceiveFrameBytes();
63 | var msg = peer2.ReceiveFrameString();
64 |
65 | Assert.Equal("Hello",msg);
66 | }
67 | }
68 | }
69 |
70 | [Fact]
71 | public void ExceptionWhenSendingToPeerWhichDoesnExist()
72 | {
73 | using (var peer1 = new PeerSocket("@inproc://peertopeer2"))
74 | {
75 | Assert.Throws(() =>
76 | {
77 | peer1.SendMoreFrame("hello"); //unexist peer
78 | peer1.SendFrame("World");
79 | });
80 | }
81 | }
82 |
83 |
84 | [Fact]
85 | public void DropMultipartMessages()
86 | {
87 | using (var peer1 = new PeerSocket("@inproc://peertopeer3"))
88 | using (var dealer = new DealerSocket(">inproc://peertopeer3"))
89 | {
90 | dealer.SendMoreFrame("This should be dropped");
91 | dealer.SendFrame("This as well");
92 | dealer.SendFrame("Hello");
93 |
94 | peer1.ReceiveFrameBytes();
95 | var message = peer1.ReceiveFrameString();
96 |
97 | Assert.Equal("Hello", message);
98 | }
99 | }
100 |
101 | }
102 | }
--------------------------------------------------------------------------------
/src/NetMQ.Tests/PushPullTests.cs:
--------------------------------------------------------------------------------
1 | using NetMQ.Sockets;
2 | using Xunit;
3 |
4 | namespace NetMQ.Tests
5 | {
6 | public class PushPullTests : IClassFixture
7 | {
8 | public PushPullTests() => NetMQConfig.Cleanup();
9 |
10 | [Fact]
11 | public void SimplePushPull()
12 | {
13 | using (var pullSocket = new PullSocket())
14 | using (var pushSocket = new PushSocket())
15 | {
16 | var port = pullSocket.BindRandomPort("tcp://127.0.0.1");
17 | pushSocket.Connect("tcp://127.0.0.1:" + port);
18 |
19 | pushSocket.SendFrame("hello");
20 |
21 | Assert.Equal("hello", pullSocket.ReceiveFrameString());
22 | }
23 | }
24 |
25 | [Fact]
26 | public void EmptyMessage()
27 | {
28 | using (var pullSocket = new PullSocket())
29 | using (var pushSocket = new PushSocket())
30 | {
31 | var port = pullSocket.BindRandomPort("tcp://127.0.0.1");
32 | pushSocket.Connect("tcp://127.0.0.1:" + port);
33 |
34 | pushSocket.SendFrame(new byte[300]);
35 |
36 | Assert.Equal(300, pullSocket.ReceiveFrameString().Length);
37 | }
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/NetMQ.Tests/RadioDish.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using NetMQ.Sockets;
4 | using Xunit;
5 | using Xunit.Abstractions;
6 |
7 | namespace NetMQ.Tests
8 | {
9 | public class RadioDish
10 | {
11 | [Fact]
12 | public void TestTcp()
13 | {
14 | using var radio = new RadioSocket();
15 | using var dish = new DishSocket();
16 | dish.Join("2");
17 |
18 | int port = radio.BindRandomPort("tcp://*");
19 | dish.Connect($"tcp://127.0.0.1:{port}");
20 |
21 | Thread.Sleep(100);
22 |
23 | radio.Send("1", "HELLO");
24 | radio.Send("2", "HELLO");
25 |
26 | var (group,msg) = dish.ReceiveString();
27 | Assert.Equal("2", group);
28 | Assert.Equal("HELLO", msg);
29 | }
30 |
31 | [Fact]
32 | public void TestBlocking()
33 | {
34 | using var radio = new RadioSocket();
35 | using var dish = new DishSocket();
36 | dish.Join("2");
37 |
38 | radio.Bind("inproc://test-radio-dish");
39 | dish.Connect("inproc://test-radio-dish");
40 |
41 | radio.Send("1", "HELLO");
42 | radio.Send("2", "HELLO");
43 |
44 | var (group,msg) = dish.ReceiveString();
45 | Assert.Equal("2", group);
46 | Assert.Equal("HELLO", msg);
47 | }
48 |
49 | [Fact]
50 | public async void TestAsync()
51 | {
52 | using var radio = new RadioSocket();
53 | using var dish = new DishSocket();
54 | dish.Join("2");
55 |
56 | int port = radio.BindRandomPort("tcp://*");
57 | dish.Connect($"tcp://127.0.0.1:{port}");
58 |
59 | Thread.Sleep(100);
60 |
61 | await radio.SendAsync("1", "HELLO");
62 | await radio.SendAsync("2", "HELLO");
63 |
64 | var (group,msg) = await dish.ReceiveStringAsync();
65 | Assert.Equal("2", group);
66 | Assert.Equal("HELLO", msg);
67 | }
68 | }
69 | }
--------------------------------------------------------------------------------
/src/NetMQ.Tests/ScatterGather.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using NetMQ.Sockets;
3 | using Xunit;
4 |
5 | namespace NetMQ.Tests
6 | {
7 | public class ScatterGather
8 | {
9 | [Fact]
10 | public void TestTcp()
11 | {
12 | using var scatter = new ScatterSocket();
13 | using var gather = new GatherSocket();
14 |
15 | int port = scatter.BindRandomPort("tcp://*");
16 | gather.Connect($"tcp://127.0.0.1:{port}");
17 |
18 | scatter.Send("1");
19 | scatter.Send("2");
20 |
21 | var m1 = gather.ReceiveString();
22 | Assert.Equal("1", m1);
23 |
24 | var m2 = gather.ReceiveString();
25 | Assert.Equal("2", m2);
26 | }
27 |
28 | [Fact]
29 | public void TestBlocking()
30 | {
31 | using var scatter = new ScatterSocket();
32 | using var gather = new GatherSocket();
33 | using var gather2 = new GatherSocket();
34 |
35 | scatter.Bind("inproc://test-scatter-gather");
36 | gather.Connect("inproc://test-scatter-gather");
37 | gather2.Connect("inproc://test-scatter-gather");
38 |
39 | scatter.Send("1");
40 | scatter.Send("2");
41 |
42 | var m1 = gather.ReceiveString();
43 | Assert.Equal("1", m1);
44 |
45 | var m2 = gather2.ReceiveString();
46 | Assert.Equal("2", m2);
47 | }
48 |
49 | [Fact]
50 | public async void TestAsync()
51 | {
52 | using var scatter = new ScatterSocket();
53 | using var gather = new GatherSocket();
54 | using var gather2 = new GatherSocket();
55 |
56 | scatter.Bind("inproc://test-scatter-gather");
57 | gather.Connect("inproc://test-scatter-gather");
58 | gather2.Connect("inproc://test-scatter-gather");
59 |
60 | await scatter.SendAsync("1");
61 | await scatter.SendAsync("2");
62 |
63 | var m1 = await gather.ReceiveStringAsync();
64 | Assert.Equal("1", m1);
65 |
66 | var m2 = await gather2.ReceiveStringAsync();
67 | Assert.Equal("2", m2);
68 | }
69 | }
70 | }
--------------------------------------------------------------------------------
/src/NetMQ.Tests/StreamTests.cs:
--------------------------------------------------------------------------------
1 | using Xunit;
2 |
3 | using NetMQ.Sockets;
4 |
5 | namespace NetMQ.Tests
6 | {
7 | public class StreamTests : IClassFixture
8 | {
9 | public StreamTests() => NetMQConfig.Cleanup();
10 |
11 | [Fact]
12 | public void StreamToStream()
13 | {
14 | using (var server = new StreamSocket())
15 | using (var client = new StreamSocket())
16 | {
17 | var port = server.BindRandomPort("tcp://*");
18 | client.Connect("tcp://127.0.0.1:" + port);
19 |
20 | byte[]? clientId = client.Options.Identity;
21 |
22 | Assert.NotNull(clientId);
23 |
24 | const string request = "GET /\r\n";
25 |
26 | const string response = "HTTP/1.0 200 OK\r\n" +
27 | "Content-Type: text/plain\r\n" +
28 | "\r\n" +
29 | "Hello, World!";
30 |
31 | client.SendMoreFrame(clientId!).SendFrame(request);
32 |
33 | byte[] serverId = server.ReceiveFrameBytes();
34 | Assert.Equal(request, server.ReceiveFrameString());
35 |
36 | server.SendMoreFrame(serverId).SendFrame(response);
37 |
38 | Assert.Equal(clientId, client.ReceiveFrameBytes());
39 | Assert.Equal(response, client.ReceiveFrameString());
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/NetMQ.Tests/ThrowingTraceListener.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Runtime.Serialization;
4 |
5 | namespace NetMQ.Tests
6 | {
7 | public sealed class ThrowingTraceListener : TraceListener
8 | {
9 | public override void Fail(string? message, string? detailMessage)
10 | {
11 | throw new DebugAssertFailureException((message + Environment.NewLine + detailMessage).Trim());
12 | }
13 |
14 | public override void Write(string? message)
15 | {
16 | }
17 |
18 | public override void WriteLine(string? message)
19 | {
20 | }
21 |
22 | [Serializable]
23 | public class DebugAssertFailureException : Exception
24 | {
25 | public DebugAssertFailureException()
26 | {
27 | }
28 |
29 | public DebugAssertFailureException(string message) : base(message)
30 | {
31 | }
32 |
33 | public DebugAssertFailureException(string message, Exception inner) : base(message, inner)
34 | {
35 | }
36 |
37 | protected DebugAssertFailureException(SerializationInfo info, StreamingContext context) : base(info, context)
38 | {
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/Command.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2009-2011 250bpm s.r.o.
3 | Copyright (c) 2007-2009 iMatix Corporation
4 | Copyright (c) 2007-2015 Other contributors as noted in the AUTHORS file
5 |
6 | This file is part of 0MQ.
7 |
8 | 0MQ is free software; you can redistribute it and/or modify it under
9 | the terms of the GNU Lesser General Public License as published by
10 | the Free Software Foundation; either version 3 of the License, or
11 | (at your option) any later version.
12 |
13 | 0MQ is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU Lesser General Public License for more details.
17 |
18 | You should have received a copy of the GNU Lesser General Public License
19 | along with this program. If not, see .
20 | */
21 |
22 | namespace NetMQ.Core
23 | {
24 | ///
25 | /// Defines a command sent between threads.
26 | ///
27 | internal struct Command
28 | {
29 | ///
30 | /// Create a new Command object for the given destination, type, and optional argument.
31 | ///
32 | /// a ZObject that denotes the destination for this command
33 | /// the CommandType of the new command
34 | /// an Object to comprise the argument for the command (optional)
35 | public Command(ZObject? destination, CommandType type, object? arg = null) : this()
36 | {
37 | Destination = destination;
38 | CommandType = type;
39 | Arg = arg;
40 | }
41 |
42 | /// The destination to which the command should be applied.
43 | public ZObject? Destination { get; }
44 |
45 | /// The type of this command.
46 | public CommandType CommandType { get; }
47 |
48 | ///
49 | /// Get the argument to this command.
50 | ///
51 | public object? Arg { get; }
52 |
53 | ///
54 | /// Override of ToString, which returns a string in the form [ command-type, destination ].
55 | ///
56 | /// a string that denotes the command-type and destination
57 | public override string ToString()
58 | {
59 | return base.ToString() + "[" + CommandType + ", " + Destination + "]";
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/ErrorHelper.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.Net.Sockets;
3 |
4 | namespace NetMQ.Core
5 | {
6 | ///
7 | /// Class ErrorHelper provides one static method - ToErrorCode, for converting a SocketError to the equivalent ErrorCode.
8 | ///
9 | internal static class ErrorHelper
10 | {
11 | ///
12 | /// Return the ErrorCode that is the closest equivalent to the given SocketError.
13 | ///
14 | /// the SocketError to convert from
15 | /// an ErrorCode that corresponds to the given SocketError
16 | public static ErrorCode ToErrorCode(this SocketError error)
17 | {
18 | switch (error)
19 | {
20 | case SocketError.AccessDenied:
21 | return ErrorCode.AccessDenied;
22 | case SocketError.Fault:
23 | return ErrorCode.Fault;
24 | case SocketError.InvalidArgument:
25 | return ErrorCode.Invalid;
26 | case SocketError.TooManyOpenSockets:
27 | return ErrorCode.TooManyOpenSockets;
28 | case SocketError.InProgress:
29 | return ErrorCode.TryAgain;
30 | case SocketError.MessageSize:
31 | return ErrorCode.MessageSize;
32 | case SocketError.ProtocolNotSupported:
33 | return ErrorCode.ProtocolNotSupported;
34 | case SocketError.AddressFamilyNotSupported:
35 | return ErrorCode.AddressFamilyNotSupported;
36 | case SocketError.AddressNotAvailable:
37 | return ErrorCode.AddressNotAvailable;
38 | case SocketError.AddressAlreadyInUse:
39 | return ErrorCode.AddressAlreadyInUse;
40 | case SocketError.NetworkDown:
41 | return ErrorCode.NetworkDown;
42 | case SocketError.NetworkUnreachable:
43 | return ErrorCode.NetworkUnreachable;
44 | case SocketError.NetworkReset:
45 | return ErrorCode.NetworkReset;
46 | case SocketError.ConnectionAborted:
47 | return ErrorCode.ConnectionAborted;
48 | case SocketError.ConnectionReset:
49 | return ErrorCode.ConnectionReset;
50 | case SocketError.NoBufferSpaceAvailable:
51 | return ErrorCode.NoBufferSpaceAvailable;
52 | case SocketError.NotConnected:
53 | return ErrorCode.NotConnected;
54 | case SocketError.TimedOut:
55 | return ErrorCode.TimedOut;
56 | case SocketError.ConnectionRefused:
57 | return ErrorCode.ConnectionRefused;
58 | case SocketError.HostUnreachable:
59 | return ErrorCode.HostUnreachable;
60 | default:
61 | Debug.Assert(false);
62 | return 0;
63 | }
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/HellloMsgSession.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ.Core
2 | {
3 | class HelloMsgSession : SessionBase
4 | {
5 | bool m_newPipe;
6 |
7 | public HelloMsgSession(IOThread ioThread, bool connect, SocketBase socket, Options options, Address addr) :
8 | base(ioThread, connect, socket, options, addr)
9 | {
10 | m_newPipe = true;
11 | }
12 |
13 | public override PullMsgResult PullMsg(ref Msg msg)
14 | {
15 | if (m_newPipe)
16 | {
17 | Assumes.NotNull(m_options.HelloMsg);
18 |
19 | m_newPipe = false;
20 | msg.InitPool(m_options.HelloMsg.Length);
21 | msg.Put(m_options.HelloMsg, 0, m_options.HelloMsg.Length);
22 | return PullMsgResult.Ok;
23 | }
24 |
25 | return base.PullMsg(ref msg);
26 | }
27 |
28 | protected override void Reset()
29 | {
30 | base.Reset();
31 | m_newPipe = true;
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/src/NetMQ/Core/IMailbox.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ.Core
2 | {
3 | internal interface IMailbox
4 | {
5 | void Send(Command command);
6 |
7 | bool TryRecv(int timeout, out Command command);
8 |
9 | void Close();
10 | }
11 | }
--------------------------------------------------------------------------------
/src/NetMQ/Core/IOThread.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2009-2011 250bpm s.r.o.
3 | Copyright (c) 2007-2009 iMatix Corporation
4 | Copyright (c) 2007-2015 Other contributors as noted in the AUTHORS file
5 |
6 | This file is part of 0MQ.
7 |
8 | 0MQ is free software; you can redistribute it and/or modify it under
9 | the terms of the GNU Lesser General Public License as published by
10 | the Free Software Foundation; either version 3 of the License, or
11 | (at your option) any later version.
12 |
13 | 0MQ is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU Lesser General Public License for more details.
17 |
18 | You should have received a copy of the GNU Lesser General Public License
19 | along with this program. If not, see .
20 | */
21 |
22 | using NetMQ.Core.Utils;
23 |
24 | namespace NetMQ.Core
25 | {
26 | internal sealed class IOThread : ZObject, IMailboxEvent
27 | {
28 | ///
29 | /// I/O thread accesses incoming commands via this mailbox.
30 | ///
31 | private readonly IOThreadMailbox m_mailbox;
32 |
33 | ///
34 | /// I/O multiplexing is performed using a poller object.
35 | ///
36 | private readonly Proactor m_proactor;
37 |
38 | #if DEBUG
39 | ///
40 | /// This gets set to "iothread-" plus the thread-id.
41 | ///
42 | private readonly string m_name;
43 | #endif
44 |
45 | ///
46 | /// Create a new IOThread object within the given context (Ctx) and thread.
47 | ///
48 | /// the Ctx (context) for this thread to live within
49 | /// the integer thread-id for this new IOThread
50 | public IOThread(Ctx ctx, int threadId)
51 | : base(ctx, threadId)
52 | {
53 | var name = "iothread-" + threadId;
54 | m_proactor = new Proactor(name);
55 | m_mailbox = new IOThreadMailbox(name, m_proactor, this);
56 |
57 | #if DEBUG
58 | m_name = name;
59 | #endif
60 | }
61 |
62 | internal Proactor Proactor => m_proactor;
63 |
64 | public void Start()
65 | {
66 | m_proactor.Start();
67 | }
68 |
69 | public void Destroy()
70 | {
71 | m_proactor.Destroy();
72 | m_mailbox.Close();
73 | }
74 |
75 | public void Stop()
76 | {
77 | SendStop();
78 | }
79 |
80 | public IMailbox Mailbox => m_mailbox;
81 |
82 | public int Load => m_proactor.Load;
83 |
84 | protected override void ProcessStop()
85 | {
86 | m_proactor.Stop();
87 | }
88 |
89 | public void Ready()
90 | {
91 | // Process all available commands.
92 | while (m_mailbox.TryRecv(out Command command))
93 | {
94 | Assumes.NotNull(command.Destination);
95 | command.Destination.ProcessCommand(command);
96 | }
97 | }
98 |
99 | #if DEBUG
100 | public override string ToString()
101 | {
102 | return base.ToString() + "[" + m_name + "]";
103 | }
104 | #endif
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/IPollEvents.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2009-2011 250bpm s.r.o.
3 | Copyright (c) 2007-2009 iMatix Corporation
4 | Copyright (c) 2007-2015 Other contributors as noted in the AUTHORS file
5 |
6 | This file is part of 0MQ.
7 |
8 | 0MQ is free software; you can redistribute it and/or modify it under
9 | the terms of the GNU Lesser General Public License as published by
10 | the Free Software Foundation; either version 3 of the License, or
11 | (at your option) any later version.
12 |
13 | 0MQ is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU Lesser General Public License for more details.
17 |
18 | You should have received a copy of the GNU Lesser General Public License
19 | along with this program. If not, see .
20 | */
21 |
22 | namespace NetMQ.Core
23 | {
24 | ///
25 | /// Classes that implement IPollEvents provide two methods (InEvent and OutEvent) that are invoked when ready for reading or writing.
26 | ///
27 | internal interface IPollEvents : ITimerEvent
28 | {
29 | ///
30 | /// Called by the I/O thread when the file descriptor is ready for reading.
31 | ///
32 | void InEvent();
33 |
34 | ///
35 | /// Called by the I/O thread when the file descriptor is ready for writing.
36 | ///
37 | void OutEvent();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/IProactorEvents.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2009-2011 250bpm s.r.o.
3 | Copyright (c) 2007-2009 iMatix Corporation
4 | Copyright (c) 2007-2015 Other contributors as noted in the AUTHORS file
5 |
6 | This file is part of 0MQ.
7 |
8 | 0MQ is free software; you can redistribute it and/or modify it under
9 | the terms of the GNU Lesser General Public License as published by
10 | the Free Software Foundation; either version 3 of the License, or
11 | (at your option) any later version.
12 |
13 | 0MQ is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU Lesser General Public License for more details.
17 |
18 | You should have received a copy of the GNU Lesser General Public License
19 | along with this program. If not, see .
20 | */
21 |
22 | using System.Net.Sockets;
23 |
24 | namespace NetMQ.Core
25 | {
26 | ///
27 | /// This is an ITimerEvent, with InCompleted and OutCompleted callback-methods,
28 | /// used for implementing a Proactor pattern.
29 | ///
30 | internal interface IProactorEvents : ITimerEvent
31 | {
32 | ///
33 | /// This is the "Input-Completed" method - called by the I/O-thread when the file descriptor is ready for reading.
34 | ///
35 | /// this is set to any socket-error that has occurred
36 | /// the number of bytes that are now ready to be read
37 | void InCompleted(SocketError socketError, int bytesTransferred);
38 |
39 | ///
40 | /// This is the "Output-Completed" method - called by the I/O thread when the file descriptor is ready for writing.
41 | ///
42 | /// this is set to any socket-error that has occurred
43 | /// the number of bytes that are now ready to be written
44 | void OutCompleted(SocketError socketError, int bytesTransferred);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/ITimerEvent.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ.Core
2 | {
3 | ///
4 | /// The ITimerEvent interface mandates a TimerEvent( int id ) method,
5 | /// that is called with an id-value when the timer expires.
6 | ///
7 | internal interface ITimerEvent
8 | {
9 | ///
10 | /// This is called when the timer expires.
11 | ///
12 | /// an integer used to identify the timer
13 | void TimerEvent(int id);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/Mechanisms/NullMechanism.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using NetMQ.Core.Utils;
4 |
5 | namespace NetMQ.Core.Mechanisms
6 | {
7 | internal class NullMechanism : Mechanism
8 | {
9 | const string ReadyCommandName = "READY";
10 | private const string ErrorCommandName = "ERROR";
11 | private const int ErrorReasonLengthSize = 1;
12 |
13 | bool m_readyCommandSent;
14 | bool m_readyCommandReceived;
15 | bool m_errorCommandReceived;
16 |
17 | public NullMechanism(SessionBase session, Options options) : base(session, options)
18 | {
19 | }
20 |
21 | public override void Dispose()
22 | {
23 | }
24 |
25 | public override MechanismStatus Status
26 | {
27 | get
28 | {
29 | if (m_readyCommandSent && m_readyCommandReceived)
30 | return MechanismStatus.Ready;
31 |
32 | bool commandSent = m_readyCommandSent;
33 | bool commandReceived = m_readyCommandReceived || m_errorCommandReceived;
34 | return commandSent && commandReceived ? MechanismStatus.Error : MechanismStatus.Handshaking;
35 | }
36 | }
37 |
38 | PushMsgResult ProcessReadyCommand(Span commandData)
39 | {
40 | m_readyCommandReceived = true;
41 | if (!ParseMetadata(commandData.Slice(ReadyCommandName.Length + 1)))
42 | return PushMsgResult.Error;
43 |
44 | return PushMsgResult.Ok;
45 | }
46 |
47 | PushMsgResult ProcessErrorCommand(Span commandData)
48 | {
49 | int fixedPrefixSize = ErrorCommandName.Length + 1 + ErrorReasonLengthSize;
50 | if (commandData.Length < fixedPrefixSize)
51 | return PushMsgResult.Error;
52 |
53 | int errorReasonLength = commandData[ErrorCommandName.Length + 1];
54 | if (errorReasonLength > commandData.Length - fixedPrefixSize)
55 | return PushMsgResult.Error;
56 |
57 | string errorReason = SpanUtility.ToAscii(commandData.Slice(fixedPrefixSize, errorReasonLength));
58 |
59 | // TODO: handle error, nothing todo at the moment as monitoring and zap are not yet implemented
60 |
61 | m_errorCommandReceived = true;
62 | return PushMsgResult.Ok;
63 | }
64 |
65 | public override PullMsgResult NextHandshakeCommand(ref Msg msg)
66 | {
67 | if (m_readyCommandSent)
68 | return PullMsgResult.Empty;
69 |
70 | MakeCommandWithBasicProperties(ref msg, ReadyCommandName);
71 | m_readyCommandSent = true;
72 |
73 | return PullMsgResult.Ok;
74 | }
75 |
76 | public override PushMsgResult ProcessHandshakeCommand(ref Msg msg)
77 | {
78 | if (m_readyCommandReceived || m_errorCommandReceived)
79 | return PushMsgResult.Error;
80 |
81 | PushMsgResult result;
82 | if (IsCommand(ReadyCommandName, ref msg))
83 | result = ProcessReadyCommand(msg);
84 | else if (IsCommand(ErrorCommandName, ref msg))
85 | result = ProcessErrorCommand(msg);
86 | else
87 | return PushMsgResult.Error;
88 |
89 | if (result == PushMsgResult.Ok)
90 | {
91 | msg.Close();
92 | msg.InitEmpty();
93 | }
94 |
95 | return result;
96 | }
97 | }
98 | }
--------------------------------------------------------------------------------
/src/NetMQ/Core/Patterns/Gather.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using NetMQ.Core.Patterns.Utils;
3 |
4 | namespace NetMQ.Core.Patterns
5 | {
6 | internal sealed class Gather : SocketBase
7 | {
8 | ///
9 | /// Fair queueing object for inbound pipes.
10 | ///
11 | private readonly FairQueueing m_fairQueueing;
12 |
13 | public Gather(Ctx parent, int threadId, int socketId)
14 | : base(parent, threadId, socketId)
15 | {
16 | m_options.SocketType = ZmqSocketType.Gather;
17 |
18 | m_fairQueueing = new FairQueueing();
19 | }
20 |
21 | ///
22 | /// Register the pipe with this socket.
23 | ///
24 | /// the Pipe to attach
25 | /// not used
26 | protected override void XAttachPipe(Pipe pipe, bool icanhasall)
27 | {
28 | Assumes.NotNull(pipe);
29 | m_fairQueueing.Attach(pipe);
30 | }
31 |
32 | ///
33 | /// Indicate the given pipe as being ready for reading by this socket.
34 | ///
35 | /// the Pipe that is now becoming available for reading
36 | protected override void XReadActivated(Pipe pipe)
37 | {
38 | m_fairQueueing.Activated(pipe);
39 | }
40 |
41 | ///
42 | /// This is an override of the abstract method that gets called to signal that the given pipe is to be removed from this socket.
43 | ///
44 | /// the Pipe that is being removed
45 | protected override void XTerminated(Pipe pipe)
46 | {
47 | m_fairQueueing.Terminated(pipe);
48 | }
49 |
50 | ///
51 | /// Receive a message. The Recv method calls this lower-level method to do the actual receiving.
52 | ///
53 | /// the Msg to receive the message into
54 | /// true if the message was received successfully, false if there were no messages to receive
55 | protected override bool XRecv(ref Msg msg)
56 | {
57 | bool received = m_fairQueueing.Recv(ref msg);
58 |
59 | // Drop any messages with more flag
60 | while (received && msg.HasMore)
61 | {
62 | // drop all frames of the current multi-frame message
63 | received = m_fairQueueing.Recv(ref msg);
64 |
65 | while (received && msg.HasMore)
66 | received = m_fairQueueing.Recv(ref msg);
67 |
68 | // get the new message
69 | if (received)
70 | received = m_fairQueueing.Recv(ref msg);
71 | }
72 |
73 | if (!received)
74 | return false;
75 |
76 | return true;
77 | }
78 |
79 | protected override bool XHasIn()
80 | {
81 | return m_fairQueueing.HasIn();
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/Patterns/Pub.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2007-2012 iMatix Corporation
3 | Copyright (c) 2009-2011 250bpm s.r.o.
4 | Copyright (c) 2007-2015 Other contributors as noted in the AUTHORS file
5 |
6 | This file is part of 0MQ.
7 |
8 | 0MQ is free software; you can redistribute it and/or modify it under
9 | the terms of the GNU Lesser General Public License as published by
10 | the Free Software Foundation; either version 3 of the License, or
11 | (at your option) any later version.
12 |
13 | 0MQ is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU Lesser General Public License for more details.
17 |
18 | You should have received a copy of the GNU Lesser General Public License
19 | along with this program. If not, see .
20 | */
21 |
22 | using System;
23 |
24 | namespace NetMQ.Core.Patterns
25 | {
26 | internal sealed class Pub : XPub
27 | {
28 | protected override void XAttachPipe(Pipe pipe, bool icanhasall)
29 | {
30 | // Don't delay pipe termination as there is no one
31 | // to receive the delimiter.
32 | pipe.SetNoDelay();
33 |
34 | base.XAttachPipe(pipe, icanhasall);
35 | }
36 |
37 | public Pub(Ctx parent, int threadId, int socketId)
38 | : base(parent, threadId, socketId)
39 | {
40 | m_options.SocketType = ZmqSocketType.Pub;
41 | }
42 |
43 | ///
44 | /// This override of the abstract XRecv method, simply throws a NotSupportedException because XRecv is not supported on a Pub socket.
45 | ///
46 | /// the Msg to receive the message into
47 | /// Messages cannot be received from PUB socket
48 | protected override bool XRecv(ref Msg msg)
49 | {
50 | // Messages cannot be received from PUB socket.
51 | throw new NotSupportedException("Messages cannot be received from PUB socket");
52 | }
53 |
54 | protected override bool XHasIn()
55 | {
56 | return false;
57 | }
58 | }
59 | }
--------------------------------------------------------------------------------
/src/NetMQ/Core/Patterns/Pull.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2007-2012 iMatix Corporation
3 | Copyright (c) 2009-2011 250bpm s.r.o.
4 | Copyright (c) 2007-2015 Other contributors as noted in the AUTHORS file
5 |
6 | This file is part of 0MQ.
7 |
8 | 0MQ is free software; you can redistribute it and/or modify it under
9 | the terms of the GNU Lesser General Public License as published by
10 | the Free Software Foundation; either version 3 of the License, or
11 | (at your option) any later version.
12 |
13 | 0MQ is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU Lesser General Public License for more details.
17 |
18 | You should have received a copy of the GNU Lesser General Public License
19 | along with this program. If not, see .
20 | */
21 |
22 | using System.Diagnostics;
23 | using NetMQ.Core.Patterns.Utils;
24 |
25 | namespace NetMQ.Core.Patterns
26 | {
27 | internal sealed class Pull : SocketBase
28 | {
29 | ///
30 | /// Fair queueing object for inbound pipes.
31 | ///
32 | private readonly FairQueueing m_fairQueueing;
33 |
34 | public Pull(Ctx parent, int threadId, int socketId)
35 | : base(parent, threadId, socketId)
36 | {
37 | m_options.SocketType = ZmqSocketType.Pull;
38 |
39 | m_fairQueueing = new FairQueueing();
40 | }
41 |
42 | ///
43 | /// Register the pipe with this socket.
44 | ///
45 | /// the Pipe to attach
46 | /// not used
47 | protected override void XAttachPipe(Pipe pipe, bool icanhasall)
48 | {
49 | Assumes.NotNull(pipe);
50 | m_fairQueueing.Attach(pipe);
51 | }
52 |
53 | ///
54 | /// Indicate the given pipe as being ready for reading by this socket.
55 | ///
56 | /// the Pipe that is now becoming available for reading
57 | protected override void XReadActivated(Pipe pipe)
58 | {
59 | m_fairQueueing.Activated(pipe);
60 | }
61 |
62 | ///
63 | /// This is an override of the abstract method that gets called to signal that the given pipe is to be removed from this socket.
64 | ///
65 | /// the Pipe that is being removed
66 | protected override void XTerminated(Pipe pipe)
67 | {
68 | m_fairQueueing.Terminated(pipe);
69 | }
70 |
71 | ///
72 | /// Receive a message. The Recv method calls this lower-level method to do the actual receiving.
73 | ///
74 | /// the Msg to receive the message into
75 | /// true if the message was received successfully, false if there were no messages to receive
76 | protected override bool XRecv(ref Msg msg)
77 | {
78 | return m_fairQueueing.Recv(ref msg);
79 | }
80 |
81 | protected override bool XHasIn()
82 | {
83 | return m_fairQueueing.HasIn();
84 | }
85 | }
86 | }
--------------------------------------------------------------------------------
/src/NetMQ/Core/Patterns/Push.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2009-2011 250bpm s.r.o.
3 | Copyright (c) 2007-2010 iMatix Corporation
4 | Copyright (c) 2007-2015 Other contributors as noted in the AUTHORS file
5 |
6 | This file is part of 0MQ.
7 |
8 | 0MQ is free software; you can redistribute it and/or modify it under
9 | the terms of the GNU Lesser General Public License as published by
10 | the Free Software Foundation; either version 3 of the License, or
11 | (at your option) any later version.
12 |
13 | 0MQ is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU Lesser General Public License for more details.
17 |
18 | You should have received a copy of the GNU Lesser General Public License
19 | along with this program. If not, see .
20 | */
21 |
22 | using System.Diagnostics;
23 | using NetMQ.Core.Patterns.Utils;
24 |
25 | namespace NetMQ.Core.Patterns
26 | {
27 | internal sealed class Push : SocketBase
28 | {
29 | ///
30 | /// Load balancer managing the outbound pipes.
31 | ///
32 | private readonly LoadBalancer m_loadBalancer;
33 |
34 | public Push(Ctx parent, int threadId, int socketId)
35 | : base(parent, threadId, socketId)
36 | {
37 | m_options.SocketType = ZmqSocketType.Push;
38 |
39 | m_loadBalancer = new LoadBalancer();
40 | }
41 |
42 | ///
43 | /// Register the pipe with this socket.
44 | ///
45 | /// the Pipe to attach
46 | /// not used
47 | protected override void XAttachPipe(Pipe pipe, bool icanhasall)
48 | {
49 | Assumes.NotNull(pipe);
50 |
51 | // Don't delay pipe termination as there is no one
52 | // to receive the delimiter.
53 | pipe.SetNoDelay();
54 |
55 | m_loadBalancer.Attach(pipe);
56 | }
57 |
58 | ///
59 | /// Indicate the given pipe as being ready for writing to by this socket.
60 | /// This gets called by the WriteActivated method.
61 | ///
62 | /// the Pipe that is now becoming available for writing
63 | protected override void XWriteActivated(Pipe pipe)
64 | {
65 | m_loadBalancer.Activated(pipe);
66 | }
67 |
68 | ///
69 | /// This is an override of the abstract method that gets called to signal that the given pipe is to be removed from this socket.
70 | ///
71 | /// the Pipe that is being removed
72 | protected override void XTerminated(Pipe pipe)
73 | {
74 | m_loadBalancer.Terminated(pipe);
75 | }
76 |
77 | ///
78 | /// Transmit the given message. The Send method calls this to do the actual sending.
79 | ///
80 | /// the message to transmit
81 | /// true if the message was sent successfully
82 | protected override bool XSend(ref Msg msg)
83 | {
84 | return m_loadBalancer.Send(ref msg);
85 | }
86 |
87 | protected override bool XHasOut()
88 | {
89 | return m_loadBalancer.HasOut();
90 | }
91 | }
92 | }
--------------------------------------------------------------------------------
/src/NetMQ/Core/Patterns/Scatter.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using NetMQ.Core.Patterns.Utils;
3 |
4 | namespace NetMQ.Core.Patterns
5 | {
6 | internal sealed class Scatter : SocketBase
7 | {
8 | ///
9 | /// Load balancer managing the outbound pipes.
10 | ///
11 | private readonly LoadBalancer m_loadBalancer;
12 |
13 | public Scatter(Ctx parent, int threadId, int socketId)
14 | : base(parent, threadId, socketId, true)
15 | {
16 | m_options.SocketType = ZmqSocketType.Scatter;
17 |
18 | m_loadBalancer = new LoadBalancer();
19 | }
20 |
21 | ///
22 | /// Register the pipe with this socket.
23 | ///
24 | /// the Pipe to attach
25 | /// not used
26 | protected override void XAttachPipe(Pipe pipe, bool icanhasall)
27 | {
28 | Assumes.NotNull(pipe);
29 |
30 | // Don't delay pipe termination as there is no one
31 | // to receive the delimiter.
32 | pipe.SetNoDelay();
33 |
34 | m_loadBalancer.Attach(pipe);
35 | }
36 |
37 | ///
38 | /// Indicate the given pipe as being ready for writing to by this socket.
39 | /// This gets called by the WriteActivated method.
40 | ///
41 | /// the Pipe that is now becoming available for writing
42 | protected override void XWriteActivated(Pipe pipe)
43 | {
44 | m_loadBalancer.Activated(pipe);
45 | }
46 |
47 | ///
48 | /// This is an override of the abstract method that gets called to signal that the given pipe is to be removed from this socket.
49 | ///
50 | /// the Pipe that is being removed
51 | protected override void XTerminated(Pipe pipe)
52 | {
53 | m_loadBalancer.Terminated(pipe);
54 | }
55 |
56 | ///
57 | /// Transmit the given message. The Send method calls this to do the actual sending.
58 | ///
59 | /// the message to transmit
60 | /// true if the message was sent successfully
61 | protected override bool XSend(ref Msg msg)
62 | {
63 | if (msg.HasMore)
64 | throw new InvalidException("SCATTER sockets do not allow multipart data (ZMQ_SNDMORE)");
65 |
66 | return m_loadBalancer.Send(ref msg);
67 | }
68 |
69 | protected override bool XHasOut()
70 | {
71 | return m_loadBalancer.HasOut();
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/Patterns/Utils/ArrayExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace NetMQ.Core.Patterns.Utils
5 | {
6 | internal static class ArrayExtensions
7 | {
8 | ///
9 | /// Make resize operation on array.
10 | ///
11 | /// Type of containing data.
12 | /// Source array.
13 | /// New size of array.
14 | /// If grow/shrink operation should be applied to the end of array.
15 | /// Resized array.
16 | public static T[] Resize(this T[] src, int size, bool ended)
17 | {
18 | T[] dest;
19 |
20 | if (size > src.Length)
21 | {
22 | dest = new T[size];
23 | if (ended)
24 | Array.Copy(src, 0, dest, 0, src.Length);
25 | else
26 | Array.Copy(src, 0, dest, size - src.Length, src.Length);
27 | }
28 | else if (size < src.Length)
29 | {
30 | dest = new T[size];
31 | if (ended)
32 | Array.Copy(src, 0, dest, 0, size);
33 | else
34 | Array.Copy(src, src.Length - size, dest, 0, size);
35 | }
36 | else
37 | {
38 | dest = src;
39 | }
40 |
41 | return dest;
42 | }
43 |
44 | public static void Swap(this List items, int index1, int index2) where T : class
45 | {
46 | if (index1 == index2)
47 | return;
48 |
49 | T item1 = items[index1];
50 | T item2 = items[index2];
51 | if (item1 != null)
52 | items[index2] = item1;
53 | if (item2 != null)
54 | items[index1] = item2;
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/Transports/IDecoder.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ.Core.Transports
2 | {
3 | internal enum DecodeResult
4 | {
5 | Error,
6 | Processing,
7 | MessageReady
8 | }
9 |
10 | internal interface IDecoder
11 | {
12 | void GetBuffer(out ByteArraySegment data, out int size);
13 |
14 | DecodeResult Decode(ByteArraySegment data, int size, out int processed);
15 |
16 | PushMsgResult PushMsg(ProcessMsgDelegate sink);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/Transports/IEncoder.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace NetMQ.Core.Transports
4 | {
5 | ///
6 | /// Interface IEncoder mandates SetMsgSource and GetData methods.
7 | ///
8 | internal interface IEncoder : IDisposable
9 | {
10 | ///
11 | /// Get a ByteArraySegment of binary data. The data
12 | /// are filled to a supplied buffer. If no buffer is supplied (data is null)
13 | /// encoder will provide buffer of its own.
14 | ///
15 | /// Returns data size or 0 when a new message is required
16 | int Encode(ref ByteArraySegment? data, int size);
17 |
18 | ///
19 | /// Load a new message into encoder.
20 | ///
21 | ///
22 | void LoadMsg(ref Msg msg);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/Transports/IEngine.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2007-2012 iMatix Corporation
3 | Copyright (c) 2009-2011 250bpm s.r.o.
4 | Copyright (c) 2011 VMware, Inc.
5 | Copyright (c) 2007-2015 Other contributors as noted in the AUTHORS file
6 |
7 | This file is part of 0MQ.
8 |
9 | 0MQ is free software; you can redistribute it and/or modify it under
10 | the terms of the GNU Lesser General Public License as published by
11 | the Free Software Foundation; either version 3 of the License, or
12 | (at your option) any later version.
13 |
14 | 0MQ is distributed in the hope that it will be useful,
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | GNU Lesser General Public License for more details.
18 |
19 | You should have received a copy of the GNU Lesser General Public License
20 | along with this program. If not, see .
21 | */
22 |
23 | namespace NetMQ.Core.Transports
24 | {
25 | ///
26 | /// Abstract interface to be implemented by various engines.
27 | ///
28 | internal interface IEngine
29 | {
30 | ///
31 | /// Plug the engine to the session.
32 | ///
33 | void Plug(IOThread ioThread, SessionBase session);
34 |
35 | ///
36 | /// Terminate and deallocate the engine. Note that 'detached'
37 | /// events are not fired on termination.
38 | ///
39 | void Terminate();
40 |
41 | ///
42 | /// This method is called by the session to signal that more
43 | /// messages can be written to the pipe.
44 | ///
45 | void ActivateIn();
46 |
47 | ///
48 | /// This method is called by the session to signal that there
49 | /// are messages to send available.
50 | ///
51 | void ActivateOut();
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/Transports/Ipc/IpcAddress.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2011 250bpm s.r.o.
3 | Copyright (c) 2011-2015 Other contributors as noted in the AUTHORS file
4 |
5 | This file is part of 0MQ.
6 |
7 | 0MQ is free software; you can redistribute it and/or modify it under
8 | the terms of the GNU Lesser General Public License as published by
9 | the Free Software Foundation; either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | 0MQ is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU Lesser General Public License for more details.
16 |
17 | You should have received a copy of the GNU Lesser General Public License
18 | along with this program. If not, see .
19 | */
20 |
21 | using System.Diagnostics.CodeAnalysis;
22 | using System.Net;
23 |
24 | namespace NetMQ.Core.Transports.Ipc
25 | {
26 | internal class IpcAddress : Address.IZAddress
27 | {
28 | private string? m_name;
29 |
30 | public override string ToString()
31 | {
32 | if (m_name == null)
33 | return string.Empty;
34 |
35 | return Protocol + "://" + m_name;
36 | }
37 |
38 | public void Resolve(string name, bool ip4Only)
39 | {
40 | m_name = name;
41 |
42 | int hash = Strings.GetStableHashCode(name);
43 | if (hash < 0)
44 | hash = -hash;
45 | hash = hash%55536;
46 | hash += 10000;
47 |
48 | this.Address = new IPEndPoint(IPAddress.Loopback, hash);
49 | }
50 |
51 | [DisallowNull]
52 | public IPEndPoint? Address { get; private set; }
53 |
54 | public string Protocol => Core.Address.IpcProtocol;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/Transports/Ipc/IpcConnector.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2011 250bpm s.r.o.
3 | Copyright (c) 2011-2015 Other contributors as noted in the AUTHORS file
4 |
5 | This file is part of 0MQ.
6 |
7 | 0MQ is free software; you can redistribute it and/or modify it under
8 | the terms of the GNU Lesser General Public License as published by
9 | the Free Software Foundation; either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | 0MQ is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU Lesser General Public License for more details.
16 |
17 | You should have received a copy of the GNU Lesser General Public License
18 | along with this program. If not, see .
19 | */
20 |
21 | using NetMQ.Core.Transports.Tcp;
22 |
23 | namespace NetMQ.Core.Transports.Ipc
24 | {
25 | ///
26 | /// IpcConnecter is a subclass of TcpConnector, which provides absolutely nothing beyond what TcpConnector does.
27 | ///
28 | internal sealed class IpcConnector : TcpConnector
29 | {
30 | public IpcConnector(IOThread ioThread, SessionBase session, Options options, Address addr, bool wait)
31 | : base(ioThread, session, options, addr, wait)
32 | {}
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/Transports/Ipc/IpcListener.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2011 250bpm s.r.o.
3 | Copyright (c) 2011-2015 Other contributors as noted in the AUTHORS file
4 |
5 | This file is part of 0MQ.
6 |
7 | 0MQ is free software; you can redistribute it and/or modify it under
8 | the terms of the GNU Lesser General Public License as published by
9 | the Free Software Foundation; either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | 0MQ is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU Lesser General Public License for more details.
16 |
17 | You should have received a copy of the GNU Lesser General Public License
18 | along with this program. If not, see .
19 | */
20 |
21 | using NetMQ.Core.Transports.Tcp;
22 |
23 | namespace NetMQ.Core.Transports.Ipc
24 | {
25 | ///
26 | /// An IpcListener is a TcpListener that also has an Address property and a SetAddress method.
27 | ///
28 | internal sealed class IpcListener : TcpListener
29 | {
30 | private readonly IpcAddress m_address;
31 |
32 | ///
33 | /// Create a new IpcListener with the given IOThread, socket, and Options.
34 | ///
35 | ///
36 | /// the SocketBase to listen to
37 | /// an Options value that dictates the settings for this IpcListener
38 | public IpcListener(IOThread ioThread, SocketBase socket, Options options)
39 | : base(ioThread, socket, options)
40 | {
41 | m_address = new IpcAddress();
42 | }
43 |
44 | ///
45 | /// Get the bound address for use with wildcards
46 | ///
47 | public override string Address => m_address.ToString();
48 |
49 | ///
50 | /// Set address to listen on.
51 | ///
52 | /// a string denoting the address to listen to
53 | public override void SetAddress(string addr)
54 | {
55 | m_address.Resolve(addr, false);
56 |
57 | Assumes.NotNull(m_address.Address);
58 |
59 | base.SetAddress(m_address.Address.Address + ":" + m_address.Address.Port);
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/Transports/Pgm/PgmAddress.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using System.Net.Sockets;
4 |
5 | namespace NetMQ.Core.Transports.Pgm
6 | {
7 | internal sealed class PgmAddress : Address.IZAddress
8 | {
9 | /// Unable to parse the address's port number, or the IP address could not be parsed.
10 | public PgmAddress(string network)
11 | {
12 | Resolve(network, true);
13 | }
14 |
15 | public PgmAddress()
16 | {
17 | }
18 |
19 | /// Unable to parse the address's port number, or the IP address could not be parsed.
20 | public void Resolve(string name, bool ip4Only)
21 | {
22 | int delimiter = name.LastIndexOf(':');
23 | if (delimiter < 0)
24 | {
25 | throw new InvalidException($"In PgmAddress.Resolve({name},{ip4Only}), delimiter ({delimiter}) must be non-negative.");
26 | }
27 |
28 | // Separate the address/port.
29 | string addrStr = name.Substring(0, delimiter);
30 | string portStr = name.Substring(delimiter + 1);
31 |
32 | if (addrStr.Contains(";"))
33 | {
34 | int semiColonDelimiter = addrStr.IndexOf(";");
35 | string interfaceIP = addrStr.Substring(0, semiColonDelimiter);
36 | addrStr = addrStr.Substring(semiColonDelimiter + 1);
37 |
38 | InterfaceAddress = IPAddress.Parse(interfaceIP);
39 | }
40 | else
41 | {
42 | InterfaceAddress = null;
43 | }
44 |
45 | // Remove square brackets around the address, if any.
46 | if (addrStr.Length >= 2 && addrStr[0] == '[' && addrStr[addrStr.Length - 1] == ']')
47 | addrStr = addrStr.Substring(1, addrStr.Length - 2);
48 |
49 | int port;
50 | // Allow 0 specifically, to detect invalid port error in atoi if not
51 | if (portStr == "*" || portStr == "0")
52 | {
53 | // Resolve wildcard to 0 to allow auto-selection of port
54 | port = 0;
55 | }
56 | else
57 | {
58 | // Parse the port number (0 is not a valid port).
59 | port = Convert.ToInt32(portStr);
60 |
61 | if (port == 0)
62 | throw new InvalidException($"In PgmAddress.Resolve({name},{ip4Only}), portStr ({portStr}) must denote a valid nonzero integer.");
63 | }
64 |
65 | if (addrStr == "*")
66 | addrStr = "0.0.0.0";
67 |
68 | if (!IPAddress.TryParse(addrStr, out IPAddress ipAddress))
69 | throw new InvalidException($"In PgmAddress.Resolve({name},{ip4Only}), addrStr ({addrStr}) must be a valid IPAddress.");
70 |
71 | this.Address = new IPEndPoint(ipAddress, port);
72 | }
73 |
74 | public IPAddress? InterfaceAddress { get; private set; }
75 |
76 | public IPEndPoint? Address { get; private set; }
77 |
78 | public override string ToString()
79 | {
80 | if (this.Address == null)
81 | return string.Empty;
82 |
83 | IPEndPoint endpoint = this.Address;
84 |
85 | return endpoint.AddressFamily == AddressFamily.InterNetworkV6
86 | ? Protocol + "://[" + endpoint.AddressFamily + "]:" + endpoint.Port
87 | : Protocol + "://" + endpoint.Address + ":" + endpoint.Port;
88 | }
89 |
90 | public string Protocol => Core.Address.PgmProtocol;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/Transports/RawDecoder.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 |
4 | namespace NetMQ.Core.Transports
5 | {
6 | internal class RawDecoder : DecoderBase
7 | {
8 | private Msg m_inProgress;
9 |
10 | private const int RawMessageReadyState = 1;
11 | private byte[] m_buffer;
12 |
13 | public RawDecoder(int bufferSize, long maxMsgSize, Endianness endianness)
14 | : base(bufferSize, endianness)
15 | {
16 | m_buffer = new byte[bufferSize];
17 | }
18 |
19 | public override void GetBuffer(out ByteArraySegment data, out int size)
20 | {
21 | data = new ByteArraySegment(m_buffer);
22 | size = m_buffer.Length;
23 | }
24 |
25 | public override DecodeResult Decode(ByteArraySegment data, int size, out int bytesUsed)
26 | {
27 | m_inProgress.InitPool(size);
28 | data.CopyTo(m_inProgress, size);
29 | bytesUsed = size;
30 | return DecodeResult.MessageReady;
31 | }
32 |
33 | protected override DecodeResult Next()
34 | {
35 | throw new NotImplementedException();
36 | }
37 |
38 | public override PushMsgResult PushMsg(ProcessMsgDelegate sink) => sink(ref m_inProgress);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/Transports/RawEncoder.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ.Core.Transports
2 | {
3 | internal class RawEncoder : EncoderBase
4 | {
5 | private const int RawMessageReadyState = 1;
6 |
7 | public RawEncoder(int bufferSize, Endianness endianness) :
8 | base(bufferSize, endianness)
9 | {
10 | NextStep(null, 0, RawMessageReadyState, true);
11 | }
12 |
13 | protected override void Next()
14 | {
15 | Assumes.NotNull(m_inProgress.UnsafeData);
16 |
17 | // Write message body into the buffer.
18 | NextStep(new ByteArraySegment(m_inProgress.UnsafeData, m_inProgress.UnsafeOffset),
19 | m_inProgress.Size, RawMessageReadyState, true);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/Transports/V1Encoder.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2007-2012 iMatix Corporation
3 | Copyright (c) 2009-2011 250bpm s.r.o.
4 | Copyright (c) 2011 VMware, Inc.
5 | Copyright (c) 2007-2015 Other contributors as noted in the AUTHORS file
6 |
7 | This file is part of 0MQ.
8 |
9 | 0MQ is free software; you can redistribute it and/or modify it under
10 | the terms of the GNU Lesser General Public License as published by
11 | the Free Software Foundation; either version 3 of the License, or
12 | (at your option) any later version.
13 |
14 | 0MQ is distributed in the hope that it will be useful,
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | GNU Lesser General Public License for more details.
18 |
19 | You should have received a copy of the GNU Lesser General Public License
20 | along with this program. If not, see .
21 | */
22 |
23 | namespace NetMQ.Core.Transports
24 | {
25 | internal class V1Encoder : EncoderBase
26 | {
27 | private const int SizeReadyState = 0;
28 | private const int MessageReadyState = 1;
29 |
30 | private readonly ByteArraySegment m_tmpbuf = new byte[10];
31 |
32 | public V1Encoder(int bufferSize, Endianness endian)
33 | : base(bufferSize, endian)
34 | {
35 | // Write 0 bytes to the batch and go to message_ready state.
36 | NextStep(m_tmpbuf, 0, MessageReadyState, true);
37 | }
38 |
39 | protected override void Next()
40 | {
41 | switch (State)
42 | {
43 | case SizeReadyState:
44 | SizeReady();
45 | break;
46 | case MessageReadyState:
47 | MessageReady();
48 | break;
49 | }
50 | }
51 |
52 | private void SizeReady()
53 | {
54 | Assumes.NotNull(m_inProgress.UnsafeData);
55 |
56 | // Write message body into the buffer.
57 | NextStep(new ByteArraySegment(m_inProgress.UnsafeData, m_inProgress.UnsafeOffset),
58 | m_inProgress.Size, MessageReadyState, true);
59 | }
60 |
61 | private void MessageReady()
62 | {
63 | m_tmpbuf.Reset();
64 |
65 | // Get the message size.
66 | int size = m_inProgress.Size;
67 |
68 | // Account for the 'flags' byte.
69 | size++;
70 |
71 | // For messages less than 255 bytes long, write one byte of message size.
72 | // For longer messages write 0xff escape character followed by 8-byte
73 | // message size. In both cases 'flags' field follows.
74 |
75 | if (size < 255)
76 | {
77 | m_tmpbuf[0] = (byte)size;
78 | m_tmpbuf[1] = (byte)(m_inProgress.Flags & MsgFlags.More);
79 | NextStep(m_tmpbuf, 2, SizeReadyState, false);
80 | }
81 | else
82 | {
83 | m_tmpbuf[0] = 0xff;
84 | m_tmpbuf.PutLong(Endian, size, 1);
85 | m_tmpbuf[9] = (byte)(m_inProgress.Flags & MsgFlags.More);
86 | NextStep(m_tmpbuf, 10, SizeReadyState, false);
87 | }
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/Transports/V2Encoder.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ.Core.Transports
2 | {
3 | ///
4 | /// Encoder for 0MQ framing protocol. Converts messages into data stream.
5 | ///
6 | internal class V2Encoder : EncoderBase
7 | {
8 | private const int SizeReadyState = 0;
9 | private const int MessageReadyState = 1;
10 |
11 | private readonly ByteArraySegment m_tmpbuf = new byte[9];
12 |
13 | public V2Encoder(int bufferSize, Endianness endian)
14 | : base(bufferSize, endian)
15 | {
16 | // Write 0 bytes to the batch and go to message_ready state.
17 | NextStep(m_tmpbuf, 0, MessageReadyState, true);
18 | }
19 |
20 | protected override void Next()
21 | {
22 | switch (State)
23 | {
24 | case SizeReadyState:
25 | SizeReady();
26 | break;
27 |
28 | case MessageReadyState:
29 | MessageReady();
30 | break;
31 | }
32 | }
33 |
34 | private void SizeReady()
35 | {
36 | Assumes.NotNull(m_inProgress.UnsafeData);
37 |
38 | // Write message body into the buffer.
39 | NextStep(new ByteArraySegment(m_inProgress.UnsafeData, m_inProgress.UnsafeOffset),
40 | m_inProgress.Size, MessageReadyState, true);
41 | }
42 |
43 | private void MessageReady()
44 | {
45 | m_tmpbuf.Reset();
46 |
47 | int protocolFlags = 0;
48 | if (m_inProgress.HasMore)
49 | protocolFlags |= V2Protocol.MoreFlag;
50 | if (m_inProgress.Size > 255)
51 | protocolFlags |= V2Protocol.LargeFlag;
52 | if (m_inProgress.HasCommand)
53 | protocolFlags |= V2Protocol.CommandFlag;
54 | m_tmpbuf[0] = (byte)protocolFlags;
55 |
56 | // Encode the message length. For messages less then 256 bytes,
57 | // the length is encoded as 8-bit unsigned integer. For larger
58 | // messages, 64-bit unsigned integer in network byte order is used.
59 | int size = m_inProgress.Size;
60 | if (size > 255)
61 | {
62 | m_tmpbuf.PutLong(Endian, size, 1);
63 | NextStep(m_tmpbuf, 9, SizeReadyState, false);
64 | }
65 | else
66 | {
67 | m_tmpbuf[1] = (byte)(size);
68 | NextStep(m_tmpbuf, 2, SizeReadyState, false);
69 | }
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/Transports/V2Protocol.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ.Core.Transports
2 | {
3 | ///
4 | /// V2Protocol is a class that contains two integer constants: MoreFlag and LargeFlag.
5 | ///
6 | internal static class V2Protocol
7 | {
8 | ///
9 | /// This is a constant-integer with the value 1.
10 | ///
11 | public const int MoreFlag = 1;
12 |
13 | ///
14 | /// This is a constant-integer with the value 2.
15 | ///
16 | public const int LargeFlag = 2;
17 |
18 | public const int CommandFlag = 4;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/Transports/V3Protocol.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ.Core.Transports
2 | {
3 | internal static class V3Protocol
4 | {
5 | public const string PingCommand = "PING";
6 | public const string PongCommand = "PONG";
7 | }
8 | }
--------------------------------------------------------------------------------
/src/NetMQ/Core/Utils/AtomicCounter.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 |
3 | namespace NetMQ.Core.Utils
4 | {
5 | ///
6 | /// This class simply provides a counter-value, which may be set, increased, and decremented.
7 | /// Increase and Decrement are both thread-safe operations.
8 | ///
9 | public sealed class AtomicCounter
10 | {
11 | private int m_value;
12 |
13 | ///
14 | /// Create a new AtomicCounter object with an initial counter-value of zero.
15 | ///
16 | public AtomicCounter()
17 | {
18 | m_value = 0;
19 | }
20 |
21 | ///
22 | /// Assign the given amount to the counter-value.
23 | ///
24 | /// the integer value to set the counter to
25 | public void Set(int amount)
26 | {
27 | m_value = amount;
28 | }
29 |
30 | ///
31 | /// Add the given amount to the counter-value, in an atomic thread-safe manner.
32 | ///
33 | /// the integer amount to add to the counter-value
34 | public void Increase(int amount)
35 | {
36 | Interlocked.Add(ref m_value, amount);
37 | }
38 |
39 | ///
40 | /// Subtract the given amount from the counter-value, in an atomic thread-safe manner.
41 | ///
42 | /// the integer amount to subtract from to the counter-value (default value is 1)
43 | /// the new value of the counter
44 | public int Decrement(int amount = 1)
45 | {
46 | return Interlocked.Add(ref m_value, amount*-1);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/Utils/ByteArrayUtility.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ.Core.Utils
2 | {
3 | internal static class ByteArrayUtility
4 | {
5 | public static bool AreEqual(byte[] a, int aOffset, byte[] b, int bOffset, int count)
6 | {
7 | if (aOffset + count > a.Length)
8 | return false;
9 |
10 | if (bOffset + count > b.Length)
11 | return false;
12 |
13 | for (int i = 0; i < count; i++)
14 | {
15 | if (a[aOffset + i] != b[bOffset + i])
16 | return false;
17 | }
18 |
19 | return true;
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/src/NetMQ/Core/Utils/SpanUtility.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 |
4 | namespace NetMQ.Core.Utils
5 | {
6 | internal static class SpanUtility
7 | {
8 | public static string ToAscii(Span bytes)
9 | {
10 | #if NETSTANDARD2_1
11 | return Encoding.ASCII.GetString(bytes);
12 | #else
13 | return Encoding.ASCII.GetString(bytes.ToArray());
14 | #endif
15 | }
16 |
17 | public static bool Equals(Span a, Span b)
18 | {
19 | if (a.Length != b.Length)
20 | return false;
21 |
22 | for (int i = 0; i < a.Length; i++)
23 | {
24 | if (a[i] != b[i])
25 | return false;
26 | }
27 |
28 | return true;
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/src/NetMQ/Core/Utils/StopSignaler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using NetMQ.Sockets;
4 |
5 | namespace NetMQ.Core.Utils
6 | {
7 | internal class StopSignaler : ISocketPollable, IDisposable
8 | {
9 | private readonly PairSocket m_writer;
10 | private readonly PairSocket m_reader;
11 | private int m_isDisposed;
12 |
13 | public StopSignaler()
14 | {
15 | PairSocket.CreateSocketPair(out m_writer, out m_reader);
16 | m_reader.ReceiveReady += delegate
17 | {
18 | m_reader.SkipFrame();
19 | IsStopRequested = true;
20 | };
21 |
22 | IsStopRequested = false;
23 | }
24 |
25 | public bool IsStopRequested { get; private set; }
26 |
27 | NetMQSocket ISocketPollable.Socket => m_reader;
28 |
29 | public bool IsDisposed => m_isDisposed != 0;
30 |
31 | public void Dispose()
32 | {
33 | if (Interlocked.CompareExchange(ref m_isDisposed, 1, 0) != 0)
34 | return;
35 | m_reader.Dispose();
36 | m_writer.Dispose();
37 | }
38 |
39 | public void Reset()
40 | {
41 | IsStopRequested = false;
42 | }
43 |
44 | public void RequestStop()
45 | {
46 | lock (m_writer)
47 | {
48 | m_writer.SignalOK();
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/NetMQ/Core/Utils/Switch.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 |
4 | namespace NetMQ.Core.Utils
5 | {
6 | internal class Switch
7 | {
8 | private readonly object m_sync;
9 | private volatile bool m_status;
10 |
11 | public Switch(bool status)
12 | {
13 | m_sync = new object();
14 | m_status = status;
15 | }
16 |
17 | public bool Status
18 | {
19 | get
20 | {
21 | lock (m_sync)
22 | {
23 | return m_status;
24 | }
25 | }
26 | }
27 |
28 | public void WaitForOff()
29 | {
30 | lock (m_sync)
31 | {
32 | // while the status is on
33 | while (m_status)
34 | {
35 | Monitor.Wait(m_sync);
36 | }
37 | }
38 | }
39 |
40 | public void WaitForOn()
41 | {
42 | lock (m_sync)
43 | {
44 | // while the status is off
45 | while (!m_status)
46 | {
47 | Monitor.Wait(m_sync);
48 | }
49 | }
50 | }
51 |
52 | public void SwitchOn()
53 | {
54 | lock (m_sync)
55 | {
56 | if (!m_status)
57 | {
58 | m_status = true;
59 | Monitor.PulseAll(m_sync);
60 | }
61 | }
62 |
63 | }
64 |
65 | public void SwitchOff()
66 | {
67 | lock (m_sync)
68 | {
69 | if (m_status)
70 | {
71 | m_status = false;
72 | Monitor.PulseAll(m_sync);
73 | }
74 | }
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/NetMQ/DnsEndPoint.cs:
--------------------------------------------------------------------------------
1 | #if NET35
2 | using System.Net;
3 |
4 | namespace NetMQ
5 | {
6 | ///
7 | /// Placeholder for System.Net.DnsEndPoint, introduced in .NET 4.0.
8 | /// This code is enabled for .NET 3.5 builds only, allowing compilation.
9 | ///
10 | internal class DnsEndPoint : EndPoint
11 | {
12 | public string Host { get; set; }
13 | public int Port { get; set; }
14 | }
15 | }
16 | #endif
17 |
--------------------------------------------------------------------------------
/src/NetMQ/EmptyArray.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ
2 | {
3 | internal static class EmptyArray
4 | {
5 | public static readonly T[] Instance = new T[0];
6 | }
7 | }
--------------------------------------------------------------------------------
/src/NetMQ/Endianness.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ
2 | {
3 | ///
4 | /// This enum-type specifies either big-endian (Big) or little-endian (Little),
5 | /// which indicate whether the most-significant bits are placed first or last in memory.
6 | ///
7 | public enum Endianness
8 | {
9 | ///
10 | /// Most-significant bits are placed first in memory.
11 | ///
12 | Big,
13 |
14 | ///
15 | /// Most-significant bits are placed last in memory.
16 | ///
17 | Little
18 | }
19 | }
--------------------------------------------------------------------------------
/src/NetMQ/EventDelegator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 |
4 | namespace NetMQ
5 | {
6 | ///
7 | /// Facilitates a pattern whereby an event may be decorated with logic that transforms its arguments.
8 | ///
9 | ///
10 | /// Use of this class requires providing actions that register and unregister a handler of the source
11 | /// event that calls with updated arguments in response.
12 | ///
13 | /// Argument type of the decorated event.
14 | internal class EventDelegator : IDisposable where T : EventArgs
15 | {
16 | private readonly Action m_registerToEvent;
17 | private readonly Action m_unregisterFromEvent;
18 | private EventHandler? m_event;
19 | private int m_counter;
20 |
21 | ///
22 | /// Initialises a new instance.
23 | ///
24 | /// an Action to perform when the first handler is registered for the event
25 | /// an Action to perform when the last handler is unregistered from the event
26 | public EventDelegator(Action registerToEvent, Action unregisterFromEvent)
27 | {
28 | m_registerToEvent = registerToEvent;
29 | m_unregisterFromEvent = unregisterFromEvent;
30 | }
31 |
32 | public event EventHandler Event
33 | {
34 | add
35 | {
36 | m_event += value;
37 |
38 | if (Interlocked.Increment(ref m_counter) == 1)
39 | m_registerToEvent();
40 | }
41 | remove
42 | {
43 | m_event -= value;
44 |
45 | if (Interlocked.Decrement(ref m_counter) == 0)
46 | m_unregisterFromEvent();
47 | }
48 | }
49 |
50 | ///
51 | /// Raise, or "Fire", the Event.
52 | ///
53 | /// the sender that the event-handler that gets notified of this event will receive
54 | /// the subclass of EventArgs that the event-handler will receive
55 | public void Fire(object sender, T args)
56 | {
57 | m_event?.Invoke(sender, args);
58 | }
59 |
60 | public void Dispose()
61 | {
62 | if (m_counter != 0)
63 | {
64 | m_unregisterFromEvent();
65 | m_counter = 0;
66 | }
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/NetMQ/INetMQPoller.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace NetMQ
4 | {
5 | ///
6 | /// Interface to of the NetMQPoller, implement to fake the NetMQPoller in tests.
7 | ///
8 | public interface INetMQPoller : IDisposable
9 | {
10 | ///
11 | /// Runs the poller on the caller's thread. Only returns when or are called from another thread.
12 | ///
13 | void Run();
14 |
15 | ///
16 | /// Runs the poller in a background thread, returning once the poller has started.
17 | ///
18 | void RunAsync();
19 |
20 | ///
21 | /// Stops the poller.
22 | ///
23 | ///
24 | /// If called from a thread other than the poller thread, this method will block until the poller has stopped.
25 | /// If called from the poller thread it is not possible to block.
26 | ///
27 | void Stop();
28 |
29 | ///
30 | /// Stops the poller, returning immediately and most likely before the poller has actually stopped.
31 | ///
32 | void StopAsync();
33 |
34 | ///
35 | /// Get whether this object is currently polling its sockets and timers.
36 | ///
37 | bool IsRunning { get; }
38 |
39 | ///
40 | /// Add a socket to the poller
41 | ///
42 | /// Socket to add to the poller
43 | void Add(ISocketPollable socket);
44 |
45 | ///
46 | /// Remove a socket from the poller
47 | ///
48 | /// The socket to be removed
49 | void Remove(ISocketPollable socket);
50 |
51 | ///
52 | /// Remove the socket from the poller and dispose the socket
53 | ///
54 | /// The socket to be removed
55 | void RemoveAndDispose(T socket) where T : ISocketPollable, IDisposable;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/NetMQ/IOutgoingSocket.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace NetMQ
4 | {
5 | ///
6 | /// Interface IOutgoingSocket mandates a Send( Msg, SendReceiveOptions ) method.
7 | ///
8 | public interface IOutgoingSocket
9 | {
10 | ///
11 | /// Send a message if one is available within .
12 | ///
13 | /// An object with message's data to send.
14 | /// The maximum length of time to try and send a message. If , no
15 | /// wait occurs.
16 | /// Indicate if another frame is expected after this frame
17 | /// true if a message was sent, otherwise false.
18 | bool TrySend(ref Msg msg, TimeSpan timeout, bool more);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/NetMQ/IReceivingSocket.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace NetMQ
4 | {
5 | ///
6 | /// Defines a socket from which message data may be read.
7 | ///
8 | public interface IReceivingSocket
9 | {
10 | ///
11 | /// Receive a message if one is available within .
12 | ///
13 | /// An object to receive the message's data into.
14 | /// The maximum length of time to wait for a message. If , no
15 | /// wait occurs.
16 | /// true if a message was received, otherwise false.
17 | bool TryReceive(ref Msg msg, TimeSpan timeout);
18 | }
19 | }
--------------------------------------------------------------------------------
/src/NetMQ/ISocketPollable.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ
2 | {
3 | ///
4 | /// Implementations provide a via the property.
5 | ///
6 | public interface ISocketPollable
7 | {
8 | ///
9 | /// Gets a instance.
10 | ///
11 | NetMQSocket Socket { get; }
12 |
13 | ///
14 | /// Gets whether the object has been disposed.
15 | ///
16 | bool IsDisposed { get; }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/NetMQ/ISocketPollableCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using NetMQ.Monitoring;
3 |
4 | namespace NetMQ
5 | {
6 | ///
7 | ///
8 | ///
9 | ///
10 | /// This interface provides an abstraction over the legacy Poller and newer classes for use in .
11 | ///
12 | [Obsolete("Use INetMQPoller instead")]
13 | public interface ISocketPollableCollection
14 | {
15 | ///
16 | /// Add a socket to a poller
17 | ///
18 | ///
19 | void Add(ISocketPollable socket);
20 |
21 | ///
22 | /// Remove a socket from poller
23 | ///
24 | ///
25 | void Remove(ISocketPollable socket);
26 |
27 | ///
28 | /// Remove a socket and dispose it
29 | ///
30 | ///
31 | ///
32 | void RemoveAndDispose(T socket) where T : ISocketPollable, IDisposable;
33 | }
34 | }
--------------------------------------------------------------------------------
/src/NetMQ/MechanismType.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ
2 | {
3 | ///
4 | /// The type of security mechanism
5 | ///
6 | public enum MechanismType
7 | {
8 | ///
9 | /// No security
10 | ///
11 | Null,
12 |
13 | ///
14 | /// Username and password mechanism over non-encrypted channel
15 | ///
16 | Plain,
17 |
18 | ///
19 | /// Curve encryption mechanism
20 | ///
21 | Curve
22 | }
23 | }
--------------------------------------------------------------------------------
/src/NetMQ/NetMQ.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | A 100% native C# port of the lightweight high performance messaging library ZeroMQ
5 | 4.0.0.0
6 | net47;netstandard2.1
7 | portable
8 | ./NetMQ.snk
9 | true
10 | true
11 | ZeroMQ;0MQ;CLRZMQ;NetMQ;Messaging;ZMQ;transport;distributed
12 | NetMQLogoSquare-256px.png
13 | https://github.com/zeromq/netmq
14 | https://github.com/zeromq/netmq/blob/master/COPYING.LESSER
15 | git
16 | https://github.com/zeromq/netmq.git
17 | true
18 | true
19 | true
20 | true
21 | true
22 | true
23 | snupkg
24 | true
25 |
26 |
27 |
28 | true
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/src/NetMQ/NetMQ.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeromq/netmq/5a3a2d0dd86b2e0e95a9582804e025c1348235c2/src/NetMQ/NetMQ.snk
--------------------------------------------------------------------------------
/src/NetMQ/NetMQProactor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using NetMQ.Sockets;
3 |
4 | namespace NetMQ
5 | {
6 | ///
7 | /// Class to quickly handle incoming messages of socket.
8 | /// New thread is created to handle the messages. Call dispose to stop the thread.
9 | /// Provided socket will not be disposed by the class.
10 | ///
11 | public class NetMQProactor : IDisposable
12 | {
13 | private readonly NetMQActor m_actor;
14 | private readonly NetMQSocket m_receiveSocket;
15 | private readonly Action m_handler;
16 | private NetMQPoller? m_poller;
17 |
18 | ///
19 | /// Create NetMQProactor and start dedicate thread to handle incoming messages.
20 | ///
21 | /// Socket to handle messages from
22 | /// Handler to handle incoming messages
23 | public NetMQProactor(NetMQSocket receiveSocket, Action handler)
24 | {
25 | m_receiveSocket = receiveSocket;
26 | m_handler = handler;
27 | m_actor = NetMQActor.Create(Run);
28 | }
29 |
30 | ///
31 | /// Stop the proactor. Provided socket will not be disposed.
32 | ///
33 | public void Dispose()
34 | {
35 | m_actor.Dispose();
36 | m_poller?.Dispose();
37 | }
38 |
39 | private void Run(PairSocket shim)
40 | {
41 | shim.ReceiveReady += OnShimReady;
42 | m_receiveSocket.ReceiveReady += OnSocketReady;
43 | m_poller = new NetMQPoller { m_receiveSocket, shim };
44 |
45 | shim.SignalOK();
46 | m_poller.Run();
47 |
48 | m_receiveSocket.ReceiveReady -= OnSocketReady;
49 | }
50 |
51 | private void OnShimReady(object sender, NetMQSocketEventArgs e)
52 | {
53 | Assumes.NotNull(m_poller);
54 |
55 | string command = e.Socket.ReceiveFrameString();
56 | if (command == NetMQActor.EndShimMessage)
57 | {
58 | m_poller.Stop();
59 | }
60 | }
61 |
62 | private void OnSocketReady(object sender, NetMQSocketEventArgs e)
63 | {
64 | NetMQMessage message = m_receiveSocket.ReceiveMultipartMessage();
65 |
66 | m_handler(m_receiveSocket, message);
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/NetMQ/NetMQSocketEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace NetMQ
4 | {
5 | ///
6 | /// This subclass of EventArgs contains a NetMQSocket,
7 | /// and IsReadyToReceive and IsReadyToSend flags to indicate whether ready to receive or send.
8 | ///
9 | public class NetMQSocketEventArgs : EventArgs
10 | {
11 | ///
12 | /// Create a new NetMQSocketEventArgs referencing the given socket.
13 | ///
14 | /// the NetMQSocket that this is in reference to
15 | public NetMQSocketEventArgs(NetMQSocket socket)
16 | {
17 | Socket = socket;
18 | }
19 |
20 | ///
21 | /// Initialise the ReceiveReady and SendReady flags from the given PollEvents value.
22 | ///
23 | /// a PollEvents value that indicates whether the socket is ready to send or receive without blocking
24 | internal void Init(PollEvents events)
25 | {
26 | IsReadyToReceive = events.HasIn();
27 | IsReadyToSend = events.HasOut();
28 | }
29 |
30 | ///
31 | /// Get the NetMQSocket that this references.
32 | ///
33 | public NetMQSocket Socket { get; }
34 |
35 | ///
36 | /// Get whether at least one message may be received by the socket without blocking.
37 | ///
38 | public bool IsReadyToReceive { get; private set; }
39 |
40 | ///
41 | /// Get whether at least one message may be sent by the socket without blocking.
42 | ///
43 | public bool IsReadyToSend { get; private set; }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/NetMQ/NetMQSynchronizationContext.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using System.Threading.Tasks;
3 |
4 | #if !NET35
5 | namespace NetMQ
6 | {
7 | internal sealed class NetMQSynchronizationContext : SynchronizationContext
8 | {
9 | private readonly NetMQPoller m_poller;
10 |
11 | public NetMQSynchronizationContext(NetMQPoller poller)
12 | {
13 | m_poller = poller;
14 | }
15 |
16 | /// Dispatches an asynchronous message to a synchronization context.
17 | public override void Post(SendOrPostCallback d, object state)
18 | {
19 | var task = new Task(() => d(state));
20 | task.Start(m_poller);
21 | }
22 |
23 | /// Dispatches a synchronous message to a synchronization context.
24 | public override void Send(SendOrPostCallback d, object state)
25 | {
26 | var task = new Task(() => d(state));
27 | task.Start(m_poller);
28 | task.Wait();
29 | }
30 | }
31 | }
32 | #endif
--------------------------------------------------------------------------------
/src/NetMQ/PollEvents.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace NetMQ
4 | {
5 | ///
6 | /// This flags enum-type is simply an indication of the direction of the poll-event,
7 | /// and can be None, PollIn, PollOut, or PollError.
8 | ///
9 | [Flags]
10 | public enum PollEvents
11 | {
12 | ///
13 | /// No events
14 | ///
15 | None = 0x0,
16 |
17 | ///
18 | /// Check for incoming
19 | ///
20 | PollIn = 0x1,
21 |
22 | ///
23 | /// Check if ready for outgoing
24 | ///
25 | PollOut = 0x2,
26 |
27 | ///
28 | /// Check if error is ready to be read
29 | ///
30 | PollError = 0x4
31 | }
32 |
33 | ///
34 | /// Extension methods for the enum.
35 | ///
36 | public static class PollEventsExtensions
37 | {
38 | /// Test whether has the flag set.
39 | public static bool HasIn(this PollEvents pollEvents)
40 | {
41 | return (pollEvents & PollEvents.PollIn) == PollEvents.PollIn;
42 | }
43 |
44 | /// Test whether has the flag set.
45 | public static bool HasOut(this PollEvents pollEvents)
46 | {
47 | return (pollEvents & PollEvents.PollOut) == PollEvents.PollOut;
48 | }
49 |
50 | /// Test whether has the flag set.
51 | public static bool HasError(this PollEvents pollEvents)
52 | {
53 | return (pollEvents & PollEvents.PollError) == PollEvents.PollError;
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/src/NetMQ/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.CompilerServices;
2 |
3 | [assembly: InternalsVisibleTo("NetMQ.Tests,PublicKey=" +
4 | "0024000004800000940000000602000000240000525341310004000001000100c90e1ebf352af7" +
5 | "132744cbb228ff09b10d7d758048085a392c57540a48f08321db8e92bc5605fb28a71339857b8d" +
6 | "63752de08cb94943b292139b34616fd8a1f216a708c0bab9685e6114bf6b8d3cbba58c556fa0bc" +
7 | "1f46970c8bd46e94c34b2c67f2220db09153f84fa0c39f5d341d84d59e3f0ccdfa033f4cfb9af5" +
8 | "01767fbb")]
9 |
10 | [assembly: InternalsVisibleTo("NetMQ.3.5.Tests,PublicKey=" +
11 | "0024000004800000940000000602000000240000525341310004000001000100c90e1ebf352af7" +
12 | "132744cbb228ff09b10d7d758048085a392c57540a48f08321db8e92bc5605fb28a71339857b8d" +
13 | "63752de08cb94943b292139b34616fd8a1f216a708c0bab9685e6114bf6b8d3cbba58c556fa0bc" +
14 | "1f46970c8bd46e94c34b2c67f2220db09153f84fa0c39f5d341d84d59e3f0ccdfa033f4cfb9af5" +
15 | "01767fbb")]
16 |
--------------------------------------------------------------------------------
/src/NetMQ/SendReceiveConstants.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 |
4 | namespace NetMQ
5 | {
6 | ///
7 | /// Constants for the send and receive operation
8 | ///
9 | public static class SendReceiveConstants
10 | {
11 | ///
12 | /// The used in string related methods that do
13 | /// not explicitly provide an encoding parameter.
14 | ///
15 | public static readonly Encoding DefaultEncoding = Encoding.UTF8;
16 |
17 | /// Indicates an infinite timeout for send and receive operations.
18 | public static readonly TimeSpan InfiniteTimeout = TimeSpan.FromMilliseconds(-1);
19 | }
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/src/NetMQ/SocketEvents.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace NetMQ
4 | {
5 | ///
6 | /// This enum-type specifies socket transport events (TCP and IPC only).
7 | ///
8 | [Flags]
9 | public enum SocketEvents
10 | {
11 | ///
12 | /// Socket got connected
13 | ///
14 | Connected = 1,
15 |
16 | ///
17 | /// Connect delayed
18 | ///
19 | ConnectDelayed = 2,
20 |
21 | ///
22 | /// Connect Retried
23 | ///
24 | ConnectRetried = 4,
25 |
26 | ///
27 | /// Socket is listening
28 | ///
29 | Listening = 8,
30 |
31 | ///
32 | /// Socket bind failed
33 | ///
34 | BindFailed = 16,
35 |
36 | ///
37 | /// Peer is accepted
38 | ///
39 | Accepted = 32,
40 |
41 | ///
42 | /// Accept failed
43 | ///
44 | AcceptFailed = 64,
45 |
46 | ///
47 | /// Socket is closed
48 | ///
49 | Closed = 128,
50 |
51 | ///
52 | /// Failed to close socket
53 | ///
54 | CloseFailed = 256,
55 |
56 | ///
57 | /// Socket disconnected
58 | ///
59 | Disconnected = 512,
60 |
61 | ///
62 | /// Listen to all events
63 | ///
64 | All = Connected | ConnectDelayed |
65 | ConnectRetried | Listening |
66 | BindFailed | Accepted |
67 | AcceptFailed | Closed |
68 | CloseFailed | Disconnected
69 | }
70 | }
--------------------------------------------------------------------------------
/src/NetMQ/Sockets/ClientSocket.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ.Sockets
2 | {
3 | ///
4 | /// Client socket, thread-safe alternative for Dealer socket
5 | ///
6 | public class ClientSocket : ThreadSafeSocket, IThreadSafeOutSocket, IThreadSafeInSocket
7 | {
8 | ///
9 | /// Create a new Client Socket.
10 | ///
11 | public ClientSocket() : base(ZmqSocketType.Client)
12 | {
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/src/NetMQ/Sockets/DealerSocket.cs:
--------------------------------------------------------------------------------
1 | using NetMQ.Core;
2 |
3 | namespace NetMQ.Sockets
4 | {
5 | ///
6 | /// A DealerSocket is a NetMQSocket, whereby the dealer sends messages in a way intended to achieve load-balancing
7 | /// - which are received in a fair queueing manner.
8 | ///
9 | public class DealerSocket : NetMQSocket
10 | {
11 | ///
12 | /// Create a new DealerSocket and attach socket to zero or more endpoints.
13 | ///
14 | /// List of NetMQ endpoints, separated by commas and prefixed by '@' (to bind the socket) or '>' (to connect the socket).
15 | /// Default action is connect (if endpoint doesn't start with '@' or '>')
16 | /// var socket = new DealerSocket(">tcp://127.0.0.1:5555,@tcp://127.0.0.1:55556");
17 | public DealerSocket(string? connectionString = null) : base(ZmqSocketType.Dealer, connectionString, DefaultAction.Connect)
18 | {
19 | }
20 |
21 | ///
22 | /// Create a new DealerSocket based upon the given SocketBase.
23 | ///
24 | /// the SocketBase to create the new socket from
25 | internal DealerSocket(SocketBase socketHandle)
26 | : base(socketHandle)
27 | {
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/NetMQ/Sockets/DishSocket.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ.Sockets
2 | {
3 | ///
4 | /// Dish socket, thread-safe alternative for SUB socket
5 | ///
6 | public class DishSocket : ThreadSafeSocket, IGroupInSocket
7 | {
8 | ///
9 | /// Create a new Client Socket.
10 | ///
11 | public DishSocket() : base(ZmqSocketType.Dish)
12 | {
13 | }
14 |
15 | ///
16 | /// Join the dish socket to a group
17 | ///
18 | /// The group to join
19 | public void Join(string group)
20 | {
21 | m_socketHandle.CheckDisposed();
22 | m_socketHandle.Join(group);
23 | }
24 |
25 | ///
26 | /// Leave a group for a dish socket
27 | ///
28 | /// The group leave
29 | public void Leave(string group)
30 | {
31 | m_socketHandle.CheckDisposed();
32 | m_socketHandle.Leave(group);
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/src/NetMQ/Sockets/GatherSocket.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ.Sockets
2 | {
3 | ///
4 | /// Gather socket, thread-safe alternative for Pull socket
5 | ///
6 | public class GatherSocket : ThreadSafeSocket, IThreadSafeInSocket
7 | {
8 | ///
9 | /// Create a new Gather Socket.
10 | ///
11 | public GatherSocket() : base(ZmqSocketType.Gather)
12 | {
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/src/NetMQ/Sockets/PairSocket.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using NetMQ.Core;
4 |
5 | namespace NetMQ.Sockets
6 | {
7 | ///
8 | /// A PairSocket is a NetMQSocket, usually used to synchronize two threads - using only one socket on each side.
9 | ///
10 | public class PairSocket : NetMQSocket
11 | {
12 | private static int s_sequence;
13 |
14 | ///
15 | /// Create a new PairSocket and attach socket to zero or more endpoints.
16 | ///
17 | /// List of NetMQ endpoints, separated by commas and prefixed by '@' (to bind the socket) or '>' (to connect the socket).
18 | /// Default action is connect (if endpoint doesn't start with '@' or '>')
19 | /// var socket = new PairSocket(">tcp://127.0.0.1:5555,@tcp://127.0.0.1:55556");
20 | public PairSocket(string? connectionString = null) : base(ZmqSocketType.Pair, connectionString, DefaultAction.Connect)
21 | {
22 | }
23 |
24 | ///
25 | /// Create a new PairSocket based upon the given SocketBase.
26 | ///
27 | /// the SocketBase to create the new socket from
28 | internal PairSocket(SocketBase socketHandle)
29 | : base(socketHandle)
30 | {
31 | }
32 |
33 | ///
34 | /// Create and return an inproc pipe where socket1 is bound and socket2 is connected.
35 | ///
36 | /// the Bind socket
37 | /// the Connect socket
38 | public static void CreateSocketPair(out PairSocket socket1, out PairSocket socket2)
39 | {
40 | string address = $"inproc://NetMQSocketPair#{Interlocked.Increment(ref s_sequence)}";
41 |
42 | socket1 = new PairSocket();
43 | socket1.Bind(address);
44 |
45 | socket2 = new PairSocket();
46 | socket2.Connect(address);
47 | }
48 |
49 | ///
50 | /// Create and return an inproc pipe where socket1 is bound and socket2 is connected.
51 | ///
52 | /// the Bind socket
53 | /// the Connect socket
54 | /// Method to initialize socket1 before connection
55 | /// Method to initialize socket2 before connection
56 | public static void CreateSocketPair(out PairSocket socket1, out PairSocket socket2, Action initSocket1, Action initSocket2)
57 | {
58 | string address = $"inproc://NetMQSocketPair#{Interlocked.Increment(ref s_sequence)}";
59 |
60 | socket1 = new PairSocket();
61 | initSocket1(socket1);
62 | socket1.Bind(address);
63 |
64 | socket2 = new PairSocket();
65 | initSocket2(socket2);
66 | socket2.Connect(address);
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/NetMQ/Sockets/PeerSocket.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using NetMQ.Core;
3 |
4 | namespace NetMQ.Sockets
5 | {
6 | ///
7 | /// Peer socket, the first message is always the identity of the sender
8 | ///
9 | public class PeerSocket : NetMQSocket
10 | {
11 | ///
12 | /// Create a new PeerSocket and attach socket to zero or more endpoints.
13 | ///
14 | /// List of NetMQ endpoints, separated by commas and prefixed by '@' (to bind the socket) or '>' (to connect the socket).
15 | /// Default action is connect (if endpoint doesn't start with '@' or '>')
16 | /// var socket = new PeerSocket(">tcp://127.0.0.1:5555,>tcp://127.0.0.1:55556");
17 | public PeerSocket(string? connectionString = null) : base(ZmqSocketType.Peer, connectionString, DefaultAction.Connect)
18 | {
19 | }
20 |
21 | ///
22 | /// Create a new PeerSocket based upon the given SocketBase.
23 | ///
24 | /// the SocketBase to create the new socket from
25 | internal PeerSocket(SocketBase socketHandle) : base(socketHandle)
26 | {
27 | }
28 |
29 | ///
30 | /// Connect the peer socket to .
31 | ///
32 | /// a string denoting the address to connect this socket to
33 | /// The peer allocated routing id
34 | /// thrown if the socket was already disposed
35 | /// The socket has been stopped.
36 | /// No IO thread was found.
37 | /// The specified address is already in use.
38 | public byte[] ConnectPeer(string address)
39 | {
40 | Connect(address);
41 | byte[]? routingId = GetSocketOptionX(ZmqSocketOption.LastPeerRoutingId);
42 | Assumes.NotNull(routingId);
43 | return routingId;
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/NetMQ/Sockets/PublisherSocket.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using NetMQ.Core;
3 |
4 | namespace NetMQ.Sockets
5 | {
6 | ///
7 | /// A PublisherSocket is a NetMQSocket intended to be used as the Pub in the PubSub pattern.
8 | /// The intended usage is for publishing messages to all subscribers which are subscribed to a given topic.
9 | ///
10 | public class PublisherSocket : NetMQSocket
11 | {
12 | ///
13 | /// Create a new PublisherSocket and attach socket to zero or more endpoints.
14 | ///
15 | /// List of NetMQ endpoints, separated by commas and prefixed by '@' (to bind the socket) or '>' (to connect the socket).
16 | /// Default action is bind (if endpoint doesn't start with '@' or '>')
17 | /// var socket = new PublisherSocket(">tcp://127.0.0.1:5555,>tcp://127.0.0.1:55556");
18 | public PublisherSocket(string? connectionString = null) : base(ZmqSocketType.Pub, connectionString, DefaultAction.Bind)
19 | {
20 | }
21 |
22 | ///
23 | /// Create a new PublisherSocket based upon the given SocketBase.
24 | ///
25 | /// the SocketBase to create the new socket from
26 | internal PublisherSocket(SocketBase socketHandle)
27 | : base(socketHandle)
28 | {
29 | }
30 |
31 | /// doesn't support sending, so this override throws .
32 | /// Receive is not supported.
33 | public override bool TryReceive(ref Msg msg, TimeSpan timeout)
34 | {
35 | throw new NotSupportedException("PublisherSocket doesn't support receiving");
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/NetMQ/Sockets/PullSocket.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using NetMQ.Core;
3 |
4 | namespace NetMQ.Sockets
5 | {
6 | ///
7 | /// A PullSocket is a NetMQSocket intended to be used as the "Pull" part of the Push-Pull pattern.
8 | /// This will "pull" messages that have been pushed from the "push" socket.
9 | ///
10 | public class PullSocket : NetMQSocket
11 | {
12 | ///
13 | /// Create a new PullSocket and attach socket to zero or more endpoints.
14 | ///
15 | /// List of NetMQ endpoints, separated by commas and prefixed by '@' (to bind the socket) or '>' (to connect the socket).
16 | /// Default action is bind (if endpoint doesn't start with '@' or '>')
17 | /// var socket = new PullSocket(">tcp://127.0.0.1:5555,>tcp://127.0.0.1:55556");
18 | public PullSocket(string? connectionString = null) : base(ZmqSocketType.Pull, connectionString, DefaultAction.Bind)
19 | {
20 | }
21 |
22 | ///
23 | /// Create a new PullSocket based upon the given SocketBase.
24 | ///
25 | /// the SocketBase to create the new socket from
26 | internal PullSocket(SocketBase socketHandle)
27 | : base(socketHandle)
28 | {
29 | }
30 |
31 | ///
32 | public override bool TrySend(ref Msg msg, TimeSpan timeout, bool more)
33 | {
34 | throw new NotSupportedException("Pull socket doesn't support sending");
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/NetMQ/Sockets/PushSocket.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using NetMQ.Core;
3 |
4 | namespace NetMQ.Sockets
5 | {
6 | ///
7 | /// A PushSocket is a NetMQSocket intended to be used as the "Push" part of the Push-Pull pattern.
8 | /// This will "push" messages to be pulled by the "pull" socket.
9 | ///
10 | public class PushSocket : NetMQSocket
11 | {
12 | ///
13 | /// Create a new PushSocket and attach socket to zero or more endpoints.
14 | ///
15 | /// List of NetMQ endpoints, separated by commas and prefixed by '@' (to bind the socket) or '>' (to connect the socket).
16 | /// Default action is connect (if endpoint doesn't start with '@' or '>')
17 | /// var socket = new PushSocket(">tcp://127.0.0.1:5555,@tcp://127.0.0.1:55556");
18 | public PushSocket(string? connectionString = null) : base(ZmqSocketType.Push, connectionString, DefaultAction.Connect)
19 | {
20 | }
21 |
22 | ///
23 | /// Create a new PushSocket based upon the given SocketBase.
24 | ///
25 | /// the SocketBase to create the new socket from
26 | internal PushSocket(SocketBase socketHandle)
27 | : base(socketHandle)
28 | {
29 | }
30 |
31 | /// doesn't support sending, so this override throws .
32 | /// Receive is not supported.
33 | public override bool TryReceive(ref Msg msg, TimeSpan timeout)
34 | {
35 | throw new NotSupportedException("PushSocket doesn't support receiving");
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/NetMQ/Sockets/RadioSocket.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ.Sockets
2 | {
3 | ///
4 | /// Radio socket, thread-safe alternative for PUB socket
5 | ///
6 | public class RadioSocket : ThreadSafeSocket, IGroupOutSocket
7 | {
8 | ///
9 | /// Create a new Client Socket.
10 | ///
11 | public RadioSocket() : base(ZmqSocketType.Radio)
12 | {
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/src/NetMQ/Sockets/ResponseSocket.cs:
--------------------------------------------------------------------------------
1 | using NetMQ.Core;
2 |
3 | namespace NetMQ.Sockets
4 | {
5 | ///
6 | /// A ResponseSocket is a NetMQSocket intended to be used as the Response part of the Request-Response pattern.
7 | /// This is generally paired with a RequestSocket.
8 | ///
9 | public class ResponseSocket : NetMQSocket
10 | {
11 | ///
12 | /// Create a new ResponseSocket and attach socket to zero or more endpoints.
13 | ///
14 | /// List of NetMQ endpoints, separated by commas and prefixed by '@' (to bind the socket) or '>' (to connect the socket).
15 | /// Default action is bind (if endpoint doesn't start with '@' or '>')
16 | /// var socket = new ResponseSocket(">tcp://127.0.0.1:5555,>tcp://127.0.0.1:55556");
17 | public ResponseSocket(string? connectionString = null) : base(ZmqSocketType.Rep, connectionString, DefaultAction.Bind)
18 | {
19 | }
20 |
21 | ///
22 | /// Create a new ResponseSocket based upon the given SocketBase.
23 | ///
24 | /// the SocketBase to create the new socket from
25 | internal ResponseSocket(SocketBase socketHandle)
26 | : base(socketHandle)
27 | {
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/NetMQ/Sockets/RouterSocket.cs:
--------------------------------------------------------------------------------
1 | using NetMQ.Core;
2 |
3 | namespace NetMQ.Sockets
4 | {
5 | ///
6 | /// Router socket, the first message is always the identity of the sender
7 | ///
8 | public class RouterSocket : NetMQSocket
9 | {
10 | ///
11 | /// Create a new RouterSocket and attach socket to zero or more endpoints.
12 | ///
13 | /// List of NetMQ endpoints, separated by commas and prefixed by '@' (to bind the socket) or '>' (to connect the socket).
14 | /// Default action is bind (if endpoint doesn't start with '@' or '>')
15 | /// var socket = new RouterSocket(">tcp://127.0.0.1:5555,>tcp://127.0.0.1:55556");
16 | public RouterSocket(string? connectionString = null) : base(ZmqSocketType.Router, connectionString, DefaultAction.Bind)
17 | {
18 | }
19 |
20 | ///
21 | /// Create a new RouterSocket based upon the given SocketBase.
22 | ///
23 | /// the SocketBase to create the new socket from
24 | internal RouterSocket(SocketBase socketHandle) : base(socketHandle)
25 | {
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/NetMQ/Sockets/ScatterSocket.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ.Sockets
2 | {
3 | ///
4 | /// Scatter socket, thread-safe alternative for Push socket
5 | ///
6 | public class ScatterSocket : ThreadSafeSocket, IThreadSafeOutSocket
7 | {
8 | ///
9 | /// Create a new Scatter Socket.
10 | ///
11 | public ScatterSocket() : base(ZmqSocketType.Scatter)
12 | {
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/src/NetMQ/Sockets/ServerSocket.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ.Sockets
2 | {
3 | ///
4 | /// Server socket, thread-safe alternative to socket.
5 | ///
6 | public class ServerSocket : ThreadSafeSocket, IRoutingIdSocket
7 | {
8 | ///
9 | /// Create a new Server Socket.
10 | ///
11 | public ServerSocket() : base(ZmqSocketType.Server)
12 | {
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/NetMQ/Sockets/StreamSocket.cs:
--------------------------------------------------------------------------------
1 | using NetMQ.Core;
2 |
3 | namespace NetMQ.Sockets
4 | {
5 | ///
6 | /// This is a NetMQSocket but provides no additional functionality.
7 | /// You can use it when you need an instance that is a NetMQSocket
8 | /// but with none of the distinguishing behavior of any of the other socket types.
9 | ///
10 | ///
11 | /// This is provided because NetMQSocket is an abstract class, so you cannot instantiate it directly.
12 | ///
13 | public class StreamSocket : NetMQSocket
14 | {
15 | ///
16 | /// Create a new StreamSocket and attach socket to zero or more endpoints.
17 | ///
18 | /// List of NetMQ endpoints, separated by commas and prefixed by '@' (to bind the socket) or '>' (to connect the socket).
19 | /// Default action is connect (if endpoint doesn't start with '@' or '>')
20 | /// var socket = new StreamSocket(">tcp://127.0.0.1:5555,@tcp://127.0.0.1:55556");
21 | public StreamSocket(string? connectionString = null) : base(ZmqSocketType.Stream, connectionString, DefaultAction.Connect)
22 | {
23 | }
24 |
25 | ///
26 | /// Create a new StreamSocket based upon the given SocketBase.
27 | ///
28 | /// the SocketBase to create the new socket from
29 | internal StreamSocket(SocketBase socketHandle)
30 | : base(socketHandle)
31 | {
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/NetMQ/TaskThread.cs:
--------------------------------------------------------------------------------
1 | #if UAP
2 | using System;
3 | using System.Globalization;
4 | using System.Threading.Tasks;
5 |
6 | namespace System.Threading
7 | {
8 | internal delegate void ParameterizedThreadStart(object obj);
9 | internal delegate void ThreadStart();
10 |
11 | internal class ThreadStateException : Exception
12 | {
13 | public ThreadStateException(string message = "", Exception innerException = null)
14 | : base(message, innerException)
15 | { }
16 | }
17 |
18 | internal class Thread
19 | {
20 | private Task _task;
21 | private CancellationTokenSource _tokenSource = new CancellationTokenSource();
22 |
23 | public string Name { get; set; }
24 | public bool IsBackground { get; set; }
25 | public bool IsAlive => _task != null && !(_task.IsCanceled || _task.IsCompleted || _task.IsFaulted);
26 | public CultureInfo CurrentCulture => throw new NotImplementedException();
27 | private static SemaphoreSlim _unavailable = new SemaphoreSlim(0, 1);
28 |
29 | private enum StartType
30 | {
31 | Standard,
32 | Parameterized
33 | };
34 |
35 | StartType _startType;
36 | ParameterizedThreadStart _parameterizedStart;
37 | ThreadStart _start;
38 |
39 | public Thread(ParameterizedThreadStart threadStart, int maxStackSize = 0)
40 | {
41 | _startType = StartType.Parameterized;
42 | _parameterizedStart = threadStart;
43 | }
44 |
45 | public Thread(ThreadStart threadStart, int maxStackSize = 0)
46 | {
47 | _startType = StartType.Standard;
48 | _start = threadStart;
49 | }
50 |
51 | public void Start()
52 | {
53 | if (_startType == StartType.Parameterized)
54 | {
55 | throw new InvalidOperationException("Must supply argument for ParameterizedThreadStart!");
56 | }
57 |
58 | if (_task != null)
59 | {
60 | throw new ThreadStateException("Thread already started!");
61 | }
62 |
63 | _task = new Task(() => _start(), _tokenSource.Token, TaskCreationOptions.LongRunning);
64 | _task.Start();
65 | }
66 |
67 | public void Start(object obj)
68 | {
69 | if (_startType == StartType.Standard)
70 | {
71 | throw new InvalidOperationException("Must use parameterless Start() method instead!");
72 | }
73 |
74 | if (_task != null)
75 | {
76 | throw new ThreadStateException("Thread already started!");
77 | }
78 |
79 | _task = new Task(() => _parameterizedStart(obj), _tokenSource.Token, TaskCreationOptions.LongRunning);
80 | _task.Start();
81 | }
82 |
83 | public void Join()
84 | {
85 | _task.Wait();
86 | }
87 |
88 | public bool Join(Int32 milliseconds)
89 | {
90 | return _task.Wait(milliseconds);
91 | }
92 |
93 | public bool Join(TimeSpan timeout)
94 | {
95 | return _task.Wait(timeout);
96 | }
97 |
98 | public static void Sleep(int milliseconds)
99 | {
100 | _unavailable.Wait(milliseconds);
101 | }
102 |
103 | public static void Sleep(TimeSpan duration)
104 | {
105 | _unavailable.Wait(duration);
106 | }
107 | }
108 | }
109 | #endif
110 |
--------------------------------------------------------------------------------
/src/NetMQ/ThreadSafeSocketExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.Threading;
3 |
4 | namespace NetMQ
5 | {
6 | ///
7 | /// Thread-safe socket extension methods
8 | ///
9 | public static class ThreadSafeSocketExtensions
10 | {
11 | ///
12 | /// Block until the message can be sent.
13 | ///
14 | ///
15 | /// The call blocks until the message can be sent and cannot be interrupted.
16 | /// Whether the message can be sent depends on the socket type.
17 | ///
18 | /// Socket to transmit on
19 | /// An object with message's data to send.
20 | public static void Send(this IThreadSafeSocket socket, ref Msg msg)
21 | {
22 | var result = socket.TrySend(ref msg, SendReceiveConstants.InfiniteTimeout);
23 | Debug.Assert(result);
24 | }
25 |
26 | ///
27 | /// Block until the next message arrives, then make the message's data available via .
28 | ///
29 | ///
30 | /// The call blocks until the next message arrives, and cannot be interrupted. This a convenient and safe when
31 | /// you know a message is available, such as for code within a callback.
32 | ///
33 | /// Socket to transmit on
34 | /// An object to receive the message's data into.
35 | /// The token to monitor for cancellation requests. The default value is .
36 | /// The token has had cancellation requested.
37 | public static void Receive(this IThreadSafeSocket socket, ref Msg msg, CancellationToken cancellationToken = default)
38 | {
39 | var result = socket.TryReceive(ref msg, SendReceiveConstants.InfiniteTimeout, cancellationToken);
40 |
41 | if (!result)
42 | cancellationToken.ThrowIfCancellationRequested();
43 |
44 | Debug.Assert(result);
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/src/NetMQ/Utils/ArrayExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace NetMQ.Utils
4 | {
5 | internal static class ArrayExtensions
6 | {
7 | public static Span Slice(this T[] array, int offset)
8 | {
9 | Span span = array;
10 | return span.Slice(offset);
11 | }
12 |
13 | public static Span Slice(this T[] array, int offset, int length)
14 | {
15 | Span span = array;
16 | return span.Slice(offset, length);
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/src/NetMQ/Utils/Assumes.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.Diagnostics.CodeAnalysis;
3 |
4 | namespace NetMQ
5 | {
6 | internal static class Assumes
7 | {
8 | #pragma warning disable CS8777 // Parameter must have a non-null value when exiting.
9 | [Conditional("DEBUG")]
10 | public static void NotNull([NotNull] T o) where T : class?
11 | {
12 | Debug.Assert(o is object, $"Unexpected null of type {typeof(T).Name}");
13 | }
14 | #pragma warning restore CS8777 // Parameter must have a non-null value when exiting.
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/NetMQ/Utils/EncodingExtensions.cs:
--------------------------------------------------------------------------------
1 | #if !NETSTANDARD2_1
2 | using System;
3 | using System.Text;
4 |
5 | namespace NetMQ.Utils
6 | {
7 | internal static class EncodingExtensions
8 | {
9 | public static unsafe void GetBytes(this Encoding encoding, string? str, Span bytes)
10 | {
11 | if (Strings.IsNullOrEmpty(str))
12 | return;
13 |
14 | fixed (char* s = str)
15 | fixed (byte* p = bytes)
16 | encoding.GetBytes(s, str.Length, p, bytes.Length);
17 | }
18 | }
19 | }
20 | #endif
21 |
--------------------------------------------------------------------------------
/src/NetMQ/Utils/Strings.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics.CodeAnalysis;
2 |
3 | namespace NetMQ
4 | {
5 | internal static class Strings
6 | {
7 | ///
8 | public static bool IsNullOrEmpty([NotNullWhen(returnValue: false)] string? s) => string.IsNullOrEmpty(s);
9 |
10 | ///
11 | public static bool IsNullOrWhiteSpace([NotNullWhen(returnValue: false)] string? s) => string.IsNullOrWhiteSpace(s);
12 |
13 | ///
14 | /// Gets a hash value from a string. This hash is stable across process invocations (doesn't use hash randomization) and across different .NET versions and platforms.
15 | ///
16 | ///
17 | /// The original code was taken from string.GetHashCode() with some minor changes
18 | /// https://github.com/microsoft/referencesource/blob/master/mscorlib/system/string.cs
19 | ///
20 | public static int GetStableHashCode(string str)
21 | {
22 | int hash1 = 5381;
23 | int hash2 = hash1;
24 |
25 | int i = 0;
26 |
27 | while (i < str.Length)
28 | {
29 | char c = str[i];
30 |
31 | hash1 = ((hash1 << 5) + hash1) ^ c;
32 |
33 | i++;
34 |
35 | if (i == str.Length)
36 | {
37 | break;
38 | }
39 |
40 | c = str[i];
41 |
42 | hash2 = ((hash2 << 5) + hash2) ^ c;
43 |
44 | i++;
45 | }
46 |
47 | return hash1 + (hash2 * 1566083941);
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/NetMQ/ZmqSocketType.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ
2 | {
3 | ///
4 | /// This enum-type is used to specify the basic type of message-queue socket
5 | /// based upon the intended pattern, such as Pub,Sub, Req,Rep, Dealer,Router, Pull,Push, Xpub,Xsub.
6 | ///
7 | public enum ZmqSocketType
8 | {
9 | ///
10 | /// No socket-type is specified
11 | ///
12 | None = -1,
13 |
14 | ///
15 | /// This denotes a Pair socket (usually paired with another Pair socket).
16 | ///
17 | Pair = 0,
18 |
19 | ///
20 | /// This denotes a Publisher socket (usually paired with a Subscriber socket).
21 | ///
22 | Pub = 1,
23 |
24 | ///
25 | /// This denotes a Subscriber socket (usually paired with a Publisher socket).
26 | ///
27 | Sub = 2,
28 |
29 | ///
30 | /// This denotes a Request socket (usually paired with a Response socket).
31 | ///
32 | Req = 3,
33 |
34 | ///
35 | /// This denotes a Response socket (usually paired with a Request socket).
36 | ///
37 | Rep = 4,
38 |
39 | ///
40 | /// This denotes an Dealer socket.
41 | ///
42 | Dealer = 5,
43 |
44 | ///
45 | /// This denotes an Router socket.
46 | ///
47 | Router = 6,
48 |
49 | ///
50 | /// This denotes a Pull socket (usually paired with a PUsh socket).
51 | ///
52 | Pull = 7,
53 |
54 | ///
55 | /// This denotes a Push socket (usually paired with a Pull socket).
56 | ///
57 | Push = 8,
58 |
59 | ///
60 | /// This denotes an XPublisher socket.
61 | ///
62 | Xpub = 9,
63 |
64 | ///
65 | /// This denotes an XSubscriber socket.
66 | ///
67 | Xsub = 10,
68 |
69 | ///
70 | /// This denotes a Stream socket - which is a parent-class to the other socket types.
71 | ///
72 | Stream = 11,
73 |
74 | ///
75 | /// This denotes an Server socket.
76 | ///
77 | Server = 12,
78 |
79 | ///
80 | /// This denotes an Client socket.
81 | ///
82 | Client = 13,
83 |
84 | ///
85 | /// This denotes an Radio socket.
86 | ///
87 | Radio = 14,
88 |
89 | ///
90 | /// This denotes an Dish socket.
91 | ///
92 | Dish = 15,
93 |
94 | ///
95 | /// This denotes an Gather socket.
96 | ///
97 | Gather = 16,
98 |
99 | ///
100 | /// This denotes an Scatter socket.
101 | ///
102 | Scatter = 17,
103 |
104 | ///
105 | /// This denotes a Peer socket.
106 | ///
107 | Peer = 19
108 | }
109 | }
--------------------------------------------------------------------------------
/src/Performance/NetMQ.SimpleTests/ITest.cs:
--------------------------------------------------------------------------------
1 | namespace NetMQ.SimpleTests
2 | {
3 | internal interface ITest
4 | {
5 | string? TestName { get; }
6 |
7 | void RunTest();
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/Performance/NetMQ.SimpleTests/NetMQ.SimpleTests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | Exe
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/Performance/NetMQ.SimpleTests/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace NetMQ.SimpleTests
4 | {
5 | internal static class Program
6 | {
7 | public static void Main()
8 | {
9 | // TODO include inproc variations
10 | // TODO print system specs, as possible
11 |
12 | ITest[] tests =
13 | {
14 | new LatencyBenchmark(),
15 | new LatencyBenchmarkReusingMsg(),
16 | new ThroughputBenchmark(),
17 | new ThroughputBenchmarkReusingMsg()
18 | };
19 |
20 | Console.WriteLine();
21 |
22 | foreach (var test in tests)
23 | {
24 | Console.WriteLine("======== {0}", test.TestName);
25 | Console.WriteLine();
26 | test.RunTest();
27 | Console.WriteLine();
28 | }
29 |
30 | Console.WriteLine();
31 | Console.WriteLine();
32 | Console.Write("Press any key to exit...");
33 | Console.ReadKey();
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/src/Performance/local_lat/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using NetMQ;
3 | using NetMQ.Sockets;
4 |
5 | namespace local_lat
6 | {
7 | internal static class Program
8 | {
9 | private static int Main(string[] args)
10 | {
11 | if (args.Length != 3)
12 | {
13 | Console.WriteLine("usage: local_lat ");
14 | return 1;
15 | }
16 |
17 | string bindTo = args[0];
18 | int messageSize = int.Parse(args[1]);
19 | int roundtripCount = int.Parse(args[2]);
20 |
21 | using (var rep = new ResponseSocket())
22 | {
23 | rep.Bind(bindTo);
24 |
25 | var msg = new Msg();
26 | msg.InitEmpty();
27 |
28 | for (int i = 0; i != roundtripCount; i++)
29 | {
30 | rep.Receive(ref msg);
31 | if (msg.Size != messageSize)
32 | {
33 | Console.WriteLine("message of incorrect size received. Received: " + msg.Size + " Expected: " + messageSize);
34 | return -1;
35 | }
36 |
37 | rep.Send(ref msg, more: false);
38 | }
39 |
40 | msg.Close();
41 | }
42 |
43 | return 0;
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/src/Performance/local_lat/local_lat.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | Exe
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/Performance/local_thr/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using NetMQ;
4 | using NetMQ.Sockets;
5 |
6 | namespace local_thr
7 | {
8 | internal static class Program
9 | {
10 | private static int Main(string[] args)
11 | {
12 | if (args.Length != 3)
13 | {
14 | Console.WriteLine("usage: local_thr ");
15 | return 1;
16 | }
17 |
18 | string bindTo = args[0];
19 | int messageSize = int.Parse(args[1]);
20 | int messageCount = int.Parse(args[2]);
21 |
22 | using (var pullSocket = new PullSocket())
23 | {
24 | pullSocket.Bind(bindTo);
25 |
26 | var msg = new Msg();
27 | msg.InitEmpty();
28 |
29 | pullSocket.Receive(ref msg);
30 |
31 | var stopWatch = Stopwatch.StartNew();
32 | for (int i = 0; i != messageCount - 1; i++)
33 | {
34 | pullSocket.Receive(ref msg);
35 | if (msg.Size != messageSize)
36 | {
37 | Console.WriteLine("message of incorrect size received. Received: " + msg.Size + " Expected: " + messageSize);
38 | return -1;
39 | }
40 | }
41 | stopWatch.Stop();
42 | var millisecondsElapsed = stopWatch.ElapsedMilliseconds;
43 | if (millisecondsElapsed == 0)
44 | millisecondsElapsed = 1;
45 |
46 | msg.Close();
47 |
48 | double messagesPerSecond = (double)messageCount/millisecondsElapsed*1000;
49 | double megabits = messagesPerSecond*messageSize*8/1000000;
50 |
51 | Console.WriteLine("message size: {0} [B]", messageSize);
52 | Console.WriteLine("message count: {0}", messageCount);
53 | Console.WriteLine("mean throughput: {0:0.000} [msg/s]", messagesPerSecond);
54 | Console.WriteLine("mean throughput: {0:0.000} [Mb/s]", megabits);
55 | }
56 |
57 | return 0;
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/src/Performance/local_thr/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/Performance/local_thr/local_thr.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | Exe
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/Performance/remote_lat/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using NetMQ;
4 | using NetMQ.Sockets;
5 |
6 | namespace remote_lat
7 | {
8 | internal static class Program
9 | {
10 | private static int Main(string[] args)
11 | {
12 | if (args.Length != 3)
13 | {
14 | Console.WriteLine("usage: remote_lat remote_lat ");
15 | return 1;
16 | }
17 |
18 | string connectTo = args[0];
19 | int messageSize = int.Parse(args[1]);
20 | int roundtripCount = int.Parse(args[2]);
21 |
22 | using (var req = new RequestSocket())
23 | {
24 | req.Connect(connectTo);
25 |
26 | var msg = new Msg();
27 | msg.InitPool(messageSize);
28 |
29 | var stopWatch = Stopwatch.StartNew();
30 |
31 | for (int i = 0; i != roundtripCount; i++)
32 | {
33 | req.Send(ref msg, more: false);
34 |
35 | req.Receive(ref msg);
36 |
37 | if (msg.Size != messageSize)
38 | {
39 | Console.WriteLine("message of incorrect size received. Received: {0} Expected: {1}", msg.Size, messageSize);
40 | return -1;
41 | }
42 | }
43 |
44 | stopWatch.Stop();
45 |
46 | msg.Close();
47 |
48 | double elapsedMicroseconds = stopWatch.ElapsedTicks*1000000L/Stopwatch.Frequency;
49 | double latency = elapsedMicroseconds/(roundtripCount*2);
50 |
51 | Console.WriteLine("message size: {0} [B]", messageSize);
52 | Console.WriteLine("roundtrip count: {0}", roundtripCount);
53 | Console.WriteLine("average latency: {0:0.000} [µs]", latency);
54 | }
55 |
56 | return 0;
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/Performance/remote_lat/remote_lat.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | Exe
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/Performance/remote_thr/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using NetMQ;
3 | using NetMQ.Sockets;
4 |
5 | namespace remote_thr
6 | {
7 | internal static class Program
8 | {
9 | private static int Main(string[] args)
10 | {
11 | if (args.Length != 3)
12 | {
13 | Console.WriteLine("usage: remote_thr ");
14 | return 1;
15 | }
16 |
17 | string connectTo = args[0];
18 | int messageSize = int.Parse(args[1]);
19 | int messageCount = int.Parse(args[2]);
20 |
21 | using (var push = new PushSocket())
22 | {
23 | push.Connect(connectTo);
24 |
25 | for (int i = 0; i != messageCount; i++)
26 | {
27 | var msg = new Msg();
28 | msg.InitPool(messageSize);
29 | push.Send(ref msg, more: false);
30 | msg.Close();
31 | }
32 | }
33 |
34 | return 0;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Performance/remote_thr/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/Performance/remote_thr/remote_thr.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | Exe
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/build.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 | :: Usage: build.bat [Clean]
3 | ::
4 | :: Requires NuGet.exe to get references NuGets prior to command line build.
5 | :: If you prefer to not install NuGet.exe fom https://nuget.org/nuget.exe,
6 | :: build first time from NetMQ.sln using DevStudio, and the referenced NuGet
7 | :: packages will be downloaded for you.
8 | :: After that first build, you can then use this script to build with no errors.
9 | ::
10 | @setlocal
11 |
12 | set ACTION=Building
13 |
14 | :: supports passing in Clean as third argument if "make clean" behavior is desired
15 | SET target=%1
16 | if /i "%target%" == "clean" set ACTION=Cleaning
17 | if NOT "%target%" == "" set target=/t:%target%
18 |
19 | :: sets version and vsversion
20 | CALL :discover_Visual_Studio_version
21 |
22 | SET solution=NetMQ.sln
23 | SET log=build_%vsversion%.log
24 | SET tools=Microsoft Visual Studio %version%\VC\vcvarsall.bat
25 | SET environment="%programfiles(x86)%\%tools%"
26 | IF NOT EXIST %environment% SET environment="%programfiles%\%tools%"
27 | IF NOT EXIST %environment% GOTO no_tools
28 |
29 |
30 | ECHO %ACTION% %solution% with DevStudio%vsversion%...
31 |
32 | :: save path
33 | @set oldpath=%PATH%
34 |
35 | CALL %environment% x86 >> %log%
36 |
37 | :: non error if not found, but build may fail
38 | ECHO Restoring referenced NuGet packages
39 | for /f %%n in ('@echo NuGet.exe') do set NUGETEXE=%%~dpf$PATH:n
40 | if NOT "%NUGETEXE%" == "" "%NUGETEXE%" restore netmq.sln
41 |
42 | ECHO Configuration=Debug
43 | msbuild /m /v:n /p:Configuration=Debug /p:Platform="Any CPU" %solution% %target% >> %log%
44 | IF errorlevel 1 GOTO error
45 | ECHO Configuration=Release
46 | msbuild /m /v:n /p:Configuration=Release /p:Platform="Any CPU" %solution% %target% >> %log%
47 | IF errorlevel 1 GOTO error
48 |
49 | : restore path
50 | @set PATH=%oldpath%
51 | set oldpath=
52 |
53 | ECHO %ACTION% complete: %solution% with DevStudio%vsversion%...
54 | GOTO end
55 |
56 |
57 | :: sets version and vsversion to on disk and product name versions of visual studio
58 | :discover_Visual_Studio_version
59 | for /f "tokens=8" %%v in ('dir /ad "c:\Program Files (x86)\microsoft visual studio *.0"') do if not "%%v" == "" call :validate_full_vs %%v
60 | set /a vsversion = %version:~0,2%
61 | if not "%vsversion%" == "" if %vsversion% gtr 10 set /a vsversion = vsversion + 1
62 | goto :eof
63 | :: make sure this actually have a VC# compiler installed
64 | :validate_full_vs
65 | set ondiskversion=%1
66 | if not exist "c:\Program Files (x86)\microsoft visual studio %ondiskversion%\Common7\Tools\vsvars32.bat" set ondiskversion=
67 | if not exist "c:\Program Files (x86)\microsoft visual studio %ondiskversion%\VC#" set ondiskversion=
68 | if not "%ondiskversion%" == "" set version=%ondiskversion%
69 | goto :eof
70 |
71 |
72 | :error
73 | if NOT "%oldpath%" == "" set PATH=%oldpath%&set oldpath=
74 | ECHO *** ERROR, build terminated early: see %log%
75 | if "%NUGETEXE%" == "" ECHO *** ERROR, Either install NuGet (https://nuget.org/nuget.exe) or do very first build using DevStudio NetMQ.sln
76 | GOTO end
77 |
78 | :no_tools
79 | ECHO *** ERROR, build tools not found: %tools%
80 |
81 | :end
82 | @endlocal
--------------------------------------------------------------------------------