{"action":"created","issue":{"url":"https://api.github.com/repos/zeromq/netmq/issues/275","labels_url":"https://api.github.com/repos/zeromq/netmq/issues/275/labels{/name}","comments_url":"https://api.github.com/repos/zeromq/netmq/issues/275/comments","events_url":"https://api.github.com/repos/zeromq/netmq/issues/275/events","html_url":"https://github.com/zeromq/netmq/issues/275","id":59413376,"number":275,"title":"Messages, Frames and the socket receiving APIs","user":{"login":"drewnoakes","id":350947,"avatar_url":"https://avatars.githubusercontent.com/u/350947?v=3","gravatar_id":"","url":"https://api.github.com/users/drewnoakes","html_url":"https://github.com/drewnoakes","followers_url":"https://api.github.com/users/drewnoakes/followers","following_url":"https://api.github.com/users/drewnoakes/following{/other_user}","gists_url":"https://api.github.com/users/drewnoakes/gists{/gist_id}","starred_url":"https://api.github.com/users/drewnoakes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/drewnoakes/subscriptions","organizations_url":"https://api.github.com/users/drewnoakes/orgs","repos_url":"https://api.github.com/users/drewnoakes/repos","events_url":"https://api.github.com/users/drewnoakes/events{/privacy}","received_events_url":"https://api.github.com/users/drewnoakes/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":27,"created_at":"2015-03-01T19:29:43Z","updated_at":"2015-03-11T00:39:16Z","closed_at":null,"body":"The extension methods for receiving from sockets are not very friendly when starting out with NetMQ. There are several ways to achieve the same thing (`SendReiveOptions.DontWait` vs `bool dontWait`) and the behaviour of non-blocking reads are not clear (do they return `null`, throw, or something else?)\r\n\r\nIn the ZeroMQ Guide, there's a distinction between messages and frames. NetMQ's API commonly refers to frames as messages. ~~This is pretty confusing and it'd be nice to get away from.~~ _Turns out that multipart message support is slated for removal in the future of ZeroMQ._\r\n\r\nHere are some ideas for how the receiving APIs might work in future.\r\n\r\n```csharp\r\n//////// BLOCKING APIS\r\n\r\n// Receiving frames\r\n\r\nFrame frame; // rename of the current Msg class\r\nsocket.ReceiveFrame(ref frame); // void return\r\n\r\nbyte[] frame = socket.ReceiveFrameBytes();\r\nbyte[] frame = socket.ReceiveFrameBytes(out more);\r\n\r\nstring frame = socket.ReceiveFrameString();\r\nstring frame = socket.ReceiveFrameString(out more);\r\nstring frame = socket.ReceiveFrameString(Encoding);\r\nstring frame = socket.ReceiveFrameString(Encoding, out more);\r\n\r\n// Receiving entire messages\r\n\r\nNetMQMessage message = socket.ReceiveMessage();\r\n\r\nList<byte[]> message = socket.ReceiveMessageBytes();\r\n\r\nList<string> message = socket.ReceiveMessageStrings();\r\nList<string> message = socket.ReceiveMessageStrings(Encoding);\r\n\r\n//////// NON-BLOCKING APIS\r\n\r\n// Receiving frames\r\n\r\nFrame frame; // rename of the current Msg class\r\nbool success = socket.TryReceiveFrame(ref frame); // void return\r\n\r\nbyte[] frame;\r\nbool success = socket.TryReceiveFrameBytes(out frame);\r\nbool success = socket.TryReceiveFrameBytes(out frame, out more);\r\nbool success = socket.TryReceiveFrameBytes(TimeSpan, out frame);\r\nbool success = socket.TryReceiveFrameBytes(TimeSpan, out frame, out more);\r\n\r\nstring frame;\r\nbool success = socket.TryReceiveFrameString(out frame);\r\nbool success = socket.TryReceiveFrameString(out frame, out more);\r\nbool success = socket.TryReceiveFrameString(out frame, Encoding);\r\nbool success = socket.TryReceiveFrameString(out frame, Encoding, out more);\r\nbool success = socket.TryReceiveFrameString(TimeSpan, out frame);\r\nbool success = socket.TryReceiveFrameString(TimeSpan, out frame, out more);\r\nbool success = socket.TryReceiveFrameString(TimeSpan, out frame, Encoding);\r\nbool success = socket.TryReceiveFrameString(TimeSpan, out frame, Encoding, out more);\r\n\r\n// Receiving entire messages\r\n\r\nNetMQMessage message;\r\nbool success = socket.TryReceiveMessage(out message);\r\nbool success = socket.TryReceiveMessage(TimeSpan, out message);\r\n\r\nList<byte[]> message;\r\nbool success = socket.TryReceiveMessageBytes(out message);\r\nbool success = socket.TryReceiveMessageBytes(TimeSpan, out message);\r\n\r\nList<string> message\r\nbool success = socket.TryReceiveMessageStrings(out message);\r\nbool success = socket.TryReceiveMessageStrings(out message, Encoding);\r\nbool success = socket.TryReceiveMessageStrings(TimeSpan, out message);\r\nbool success = socket.TryReceiveMessageStrings(TimeSpan, out message, Encoding);\r\n```\r\n\r\nBlocking receives never return `null`. The non-blocking versions always set their out params to `null` when they return `false` (or in the case of the `ref` param, they leave it unmodified).\r\n\r\nThe `SendReceiveOptions` enum makes the current API confusing. Is it valid to receive and set `SendMore`? I guess this is a throwback to the C API's enum where this kind of thing would seem more natural, but here it's confusing. I've deliberately left it out of the above, though another option would be to split it into `SendOptions` and `ReceiveOptions`.\r\n\r\nRather than using the `bool dontWait` value throughout, the above makes a distinction between a blocking receive, and a 'try' receive, which indicates failure with a boolean return value, not an `AgainException`. Exceptions should only be used for exceptional circumstances, not something as commonplace as there being nothing to receive. It's also more idiomatic in .NET to have a `Try*` method for operations which may fail, and users should know the semantics of the return value.\r\n\r\nOverloads which take `TimeSpan` timeouts would only be available on `NetMQSocket`, not `IReceivingSocket` (unless the latter was modified to include a timeout in its interface&mdash;I'm unsure if this is feasible).\r\n\r\nWould like to hear people's thoughts."},"comment":{"url":"https://api.github.com/repos/zeromq/netmq/issues/comments/78179097","html_url":"https://github.com/zeromq/netmq/issues/275#issuecomment-78179097","issue_url":"https://api.github.com/repos/zeromq/netmq/issues/275","id":78179097,"user":{"login":"drewnoakes","id":350947,"avatar_url":"https://avatars.githubusercontent.com/u/350947?v=3","gravatar_id":"","url":"https://api.github.com/users/drewnoakes","html_url":"https://github.com/drewnoakes","followers_url":"https://api.github.com/users/drewnoakes/followers","following_url":"https://api.github.com/users/drewnoakes/following{/other_user}","gists_url":"https://api.github.com/users/drewnoakes/gists{/gist_id}","starred_url":"https://api.github.com/users/drewnoakes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/drewnoakes/subscriptions","organizations_url":"https://api.github.com/users/drewnoakes/orgs","repos_url":"https://api.github.com/users/drewnoakes/repos","events_url":"https://api.github.com/users/drewnoakes/events{/privacy}","received_events_url":"https://api.github.com/users/drewnoakes/received_events","type":"User","site_admin":false},"created_at":"2015-03-11T00:39:16Z","updated_at":"2015-03-11T00:39:16Z","body":"In general the user should be aware of and control encoding. However it seems that UTF-8 has pretty much won the encodings battle for most of the planet, and is likely the best choice. Whether changing this might cause issues, I'm not certain. It seems unlikely to be a harmful change, as UTF-8 is a strict superset of ASCII."}}