Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

This is great, but, to complement this, does anyone know a better alternative to TCP? I've recently needed to make two processes communicate over the network and, while MessagePack handles the serialization, I found myself needing something higher level than TCP but lower than HTTP.

An annoyance of TCP was that I never knew whether I read all the data. I either read less and leave data unread, or I read more and end up blocking for a long time (or implement timeouts and get the worst of both worlds).

What's a good alternative? Maybe 0mq? All I need is to send some MsgPack bytes to another client over the wire, hopefully without having to guess whether there's more to read in the socket or not.



ØMQ is probably a good fit (I think nanomsg is dead?) but there are also a number of protocols at the TCP level that provide a message-sequence interface rather than a byte-sequence interface: SCTP is perhaps the best-known, and Plan9 IL is another (deprecated) solution.

For some applications, though, the simplest solution is to shut down one half of the TCP connection once you've finished sending your data. That's how rsh, finger, and HTTP/0.9 responses work, and it's a supported option in HTTP/1.0 and HTTP/1.1. Failing that, preceding each message with a byte count, a la netstrings, is fairly simple; or you can use SLIP-like or COBS framing.


Hmm, interesting, and 0mq is a bit heavy. Unfortunately I can't shut down the connection, as the server needs to provide real-time updates to the clients (its pub/sub), but I'll look into STCP, thanks.


There are a couple of ghetto ways to do pubsub. Webhooks is one, and it's often by far the easiest to implement, but in other cases it's impossible. "Long polling" is another: you open a connection and tell the server what you think the current state of a variable is, and the server just sits there with the connection open until that isn't the current state of the variable any more, at which point it sends you the new current state, or the delta from the state you had to the current state, and closes the connection. If you were wrong about the current state, this happens immediately. Again, though, there are pubsub cases where this works, and pubsub cases where the extra latency and kernel CPU of opening a new TCP connection for every message are intolerable.

So, to take the canonical concrete example, a chat channel might number the messages on it in a monotonically increasing order, and you might tell the server the channel name and the number of the last message you saw, at which point it sends you the messages since that point, if any, then closes the connection. As I understand it, this is how Kafka works, except for the connection-closing part.

In all probability, your life will be easier and your performance will be better with ØMQ, but these hacks are things that work reasonably well and are extremely easy to implement with off-the-shelf tech.

SCTP in many cases suffers from the fact that it doesn't run on top of TCP, so NATs don't know what to do with it. If you have enough control over your network that that isn't a concern for you, UDP with IP multicast is another plausible solution, the one TIBCO used originally IIRC; you can allocate a multicast IP address per pubsub channel or multiplex them. With IP multicast, recovery from lost messages is a concern, especially if 802.11 is part of your network (since 802.11 uses hop-by-hop ACKs for unicast packets) but there are a variety of reliable multicast protocols like SRM to handle that.

Feel free to hit me up for more info, I've been hacking around with different ways of doing pubsub since the previous millennium.


That's very informative, thank you for taking the time. Just so you have more context, this is what I'm using this in:

https://gitlab.com/stavros/itsalive

Clients can connect to the server and get updates for the commands that are currently running, which is not high throughput or complex from a networking perspective. I was wondering if there was something lightweight that will do the same, and 0mq seems like the best choice, but a simple loop over the connections seems to work well as well.

I played around with 0mq for this and it works great, but in this instance I might not want to add the extra dependency (especially since I've already implemented it, minus a bug where it'll block if a packet is exactly 4k).

I think adding an "end of message" character (eg a newline) would be the simplest thing to do in this instance.


Yeah, that sounds like the best choice. (That's the SLIP framing approach.) SCTP probably isn't viable if you want random people to be able to watch the presentation without rebuilding their kernels, and multicast IP isn't viable on the global internet. An IRC server would work fine, and you might even be able to just use a secret channel on Freenode, but some places block IRC because of other pubsub software that uses it.


Yeah, I wouldn't want to burden Freenode with that, but IRC is an interesting choice. I'll use the terminating character, thanks for your time!


Right, the benefit of using IRC is that you don't have to write the server; there are dozens of well-known, actively-maintained free-software servers, they're well-documented, and they already support epoll and kqueue and have reasonable ways of handling all kinds of pathological network conditions. But maybe a simple asyncio-based event loop, or even threads, would be fine for itsalive.


Do you mean just opening a port and listening for connections? And a client which connects to that port and sends/receives data? That's not very low level and it's pretty easy to do, if I'm understanding you correctly.


How do you guarantee that you've read the entire buffer without trying to read more and blocking?


Maybe I misunderstood but if you add a length header to every packet reading becomes trivial.


It does, but if I can have a library handle that for me, that'd be better. Looks like 0mq is what I want, it also does pub/sub so it frees me from doing that myself.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: