Skip to content

Commit cc4dd5c

Browse files
authored
Merge pull request #870 from dhyams/relaxed_correlate_docs_866
Relaxed/correlate socket option docs #866
2 parents e32655a + fd24ada commit cc4dd5c

File tree

3 files changed

+74
-6
lines changed

3 files changed

+74
-6
lines changed

docs/introduction.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,12 @@ NetMQ comes with several options that will effect how things work.
165165

166166
Depending on the type of sockets you are using, or the topology you are attempting to create, you may find that you need to set some ZeroMQ options. In NetMQ this is done using the `NetMQSocket.Options` property.
167167

168-
Here is a listing of the available properties that you may set on a `NetMQSocket`. It is hard to say exactly which of these values you may need to set, as that obviously depends entirely on what you are trying to achieve. All I can do is list the options, and make you aware of them. So here they are:
168+
Here is a listing of the available options that you may set on a `NetMQSocket`. It is hard to say exactly which of these values you may need to set, as that obviously depends entirely on what you are trying to achieve. All I can do is list the options, and make you aware of them. So here they are:
169169

170170
+ `Affinity`
171171
+ `BackLog`
172172
+ `CopyMessages`
173+
+ `Correlate`
173174
+ `DelayAttachOnConnect`
174175
+ `Endian`
175176
+ `GetLastEndpoint`
@@ -185,6 +186,7 @@ Here is a listing of the available properties that you may set on a `NetMQSocket
185186
+ `ReceiveBuffer`
186187
+ `ReconnectInterval`
187188
+ `ReconnectIntervalMax`
189+
+ `Relaxed`
188190
+ `SendHighWaterMark`
189191
+ `SendTimeout`
190192
+ `SendBuffer`
@@ -194,4 +196,4 @@ Here is a listing of the available properties that you may set on a `NetMQSocket
194196
+ `TcpKeepaliveInterval`
195197
+ `XPubVerbose`
196198

197-
We will not be covering all of these here, but shall instead cover them in the areas where they are used. For now just be aware that if you have read something in the <a href="http://zguide.zeromq.org/page:all" target="_blank">ZeroMQ guide</a> that mentions some option, that this is most likely the place you will need to set it/read from it.
199+
We will not be covering all of these here, but shall instead cover them in the areas where they are used. For now just be aware that if you have read something in the <a href="http://zguide.zeromq.org/page:all" target="_blank">ZeroMQ guide</a> that mentions some option, that this is most likely the place you will need to set it/read from it. Also, the socket options are described in the <a href="http://api.zeromq.org/master:zmq-setsockopt" target="_blank">zmq_setsockopt</a> documentation.

docs/request-response.md

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Anyway we digress, this post is about Request/Response, so lets continue to look
1212

1313
Request / Response pattern is a configuration of two NetMQ sockets working harmoniously together. This combination of sockets are akin to what you might see when you make a web request. That is, you make a request and you expect a response.
1414

15-
`RequestSocket` and `ResponseSocket` are **synchronous**, **blocking**, and throw exceptions if you try to read messages in the wrong order.
15+
`RequestSocket` and `ResponseSocket` are **synchronous**, **blocking**, and throw exceptions if you try to read messages in the wrong order (however; see below for socket options that allow relaxing of this strict rule).
1616

1717
The way you should work with connected `RequestSocket` and `ResponseSocket`s is as follows:
1818

@@ -21,7 +21,7 @@ The way you should work with connected `RequestSocket` and `ResponseSocket`s is
2121
3. The `ResponseSocket` sends the response message
2222
4. The `RequestSocket` receives the message from the `ResponseSocket`
2323

24-
Believe it or not you have more than likely already seen this example on numerous occasions as it is the simplest to demonstrate.
24+
Believe it or not, you have more than likely already seen this example on numerous occasions as it is the simplest to demonstrate.
2525

2626
Here is a small example where the `RequestSocket` and `ResponseSocket`s are both in the same process, but this could be easily split between two processes. We are keeping this as simple as possible for demonstration purposes.
2727

@@ -50,7 +50,7 @@ When you run this demo code you should see something like this:
5050

5151
## Request/Response is blocking
5252

53-
As stated above `RequestSocket` and `ResponseSocket` are blocking, which means any unexpected send or receive calls to **WILL** result in exceptions. Here is an example of just such an exception.
53+
As stated above `RequestSocket` and `ResponseSocket` are blocking, which means any unexpected send or receive calls to **WILL** result in exception being thrown. Here is an example of just such an exception.
5454

5555
In this example we try and call `Send()` twice from the `RequestSocket`
5656

@@ -60,4 +60,39 @@ Or how about this example where we try and call `RecieveString()` twice, but the
6060

6161
![](Images/RequestResponse2Receives.png)
6262

63-
So be careful what you do with the Request/Response pattern, the devil is in the detail.
63+
So be careful what you do with the Request/Response pattern; the devil is in the details.
64+
65+
## Relaxing the strict req/rep pattern
66+
67+
If you have set the Relaxed and Correlate options for your request socket, you can send
68+
multiple times from a request socket before a response arrives.
69+
When you get a response back, that response will be a reply to the last sent request. Please
70+
note, however, that this does not absolve the ResponseSocket from servicing all of the requests
71+
that have come in; the only difference is that on the Requesting side, you will "see" only
72+
one of the responses; the one for the latest request.
73+
74+
This functionality is useful for situations in which the responder might unexpectedly disconnect,
75+
as well as being able to reliably query to see if a response socket is available before sending
76+
a real request. See the <a href="http://api.zeromq.org/master:zmq-setsockopt" target="_blank">documentation for the native ZMQ library</a> at for more details.
77+
78+
A small example follows:
79+
80+
``` csharp
81+
using (var rep = new ResponseSocket())
82+
using (var req = new RequestSocket())
83+
{
84+
var port = rep.BindRandomPort($"tcp://127.0.0.1");
85+
req.Connect($"tcp://127.0.0.1:{port}");
86+
req.Options.Correlate = correlate;
87+
req.Options.Relaxed = true;
88+
89+
req.SendFrame("Request1");
90+
req.SendFrame("Request2");
91+
92+
rep.SendFrame(rep.ReceiveFrameString());
93+
rep.SendFrame(rep.ReceiveFrameString());
94+
95+
// the result here will be "Request2".
96+
Console.WriteLine(req.ReceiveFrameString());
97+
}
98+
```

src/NetMQ.Tests/ReqRepTests.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,37 @@ public void SingleResponderSendsCorrectMessagesToMultipleRequestors()
176176
}
177177
}
178178

179+
[Theory]
180+
[InlineData(false)]
181+
[InlineData(true)]
182+
public void ReplyIsForLatestRequestIfRelaxedAndCorrelateEnabled(bool correlate)
183+
{
184+
using (var rep = new ResponseSocket())
185+
using (var req = new RequestSocket())
186+
{
187+
var port = rep.BindRandomPort($"tcp://127.0.0.1");
188+
189+
req.Connect($"tcp://127.0.0.1:{port}");
190+
req.Options.Correlate = correlate;
191+
req.Options.Relaxed = true;
192+
193+
req.SendFrame("Request1");
194+
req.SendFrame("Request2");
195+
196+
rep.SendFrame(rep.ReceiveFrameString());
197+
rep.SendFrame(rep.ReceiveFrameString());
198+
199+
if (correlate)
200+
{
201+
Assert.Equal("Request2", req.ReceiveFrameString());
202+
}
203+
else
204+
{
205+
Assert.Equal("Request1", req.ReceiveFrameString());
206+
}
207+
}
208+
}
209+
179210
internal void RouterBounce(ref RouterSocket router)
180211
{
181212
bool more;

0 commit comments

Comments
 (0)