2

I have a server which maintains some shares state.

The clients can send some requests and get an answer from the server.

Sometimes the server needs to give some information to the client asynchronously (without getting a request first)

To make it easier on myself I would create two TCP conntections. The first where the client would initiate a request and get an answer, and the second one where the server would initiate (and optionally get an answer).

I know in theory this could be done in a single connection, but you could run into the problem where the client requests some information and the server would respond first with some request to the client instead of the answer. So there has to be logic to classify what the server has send, instead of just assuming that it is the answer to the request.

Because I did not find this pattern in the wild yet, are there any downsides?

3
  • A significant downside is that many clients are behind firewalls that block any incoming connections, preventing the server from initiating any connections to the client.
    – JonasH
    Commented Oct 3, 2023 at 13:03
  • 1
    This sounds like a problem for which QUIC was made for: you got multiple streams, including both server-initiated and client-initiated ones. (In HTTP/3, you would use one stream per request-response pair, but you can do it differently.) Commented Oct 3, 2023 at 21:08
  • "there has to be logic to classify what the server has send, instead of just assuming that it is [an] answer" - it's always good to verify that anyway. If your protocol has no headers that allow distinguishing answers from queries, i.e. it sends only the raw payload, I'd consider that a problem.
    – Bergi
    Commented Oct 3, 2023 at 21:54

3 Answers 3

6

FTP used to work like this: a control connection and a separate data connection. SIP still works like this under some circumstances. It's not unusual for video or telephony applications to have a "control" channel (bidirectional request/response) and a "data" stream, derived from the separate control and data planes of traditional telephones. You might even have a TCP control channel and a UDP data channel.

The first problem: how do you initiate these connections? Server-to-client initiation is basically impossible at scale due to firewalls, so you have to have the client create two connections.

Then: how do you manage them? You have to have some means of turning around the connection (possibly just a different port), and some means of associating it with the same client as the other connection.

Another consideration: what if one of them breaks?

you could run into the problem where the client requests some information and the server would respond first with some request to the client instead of the answer. So there has to be logic to classify what the server has send, instead of just assuming that it is the answer to the request.

This is fine with a little additional book-keeping.

I strongly suggest that you use one of the existing protocols which solves this problem, such as HTTP/2 (as used by GRPC) or WebSockets.

2

That can be done but may in practice be more brittle than a simple multiplexing protocol over a single connection, as you have more potentially failing parts. Multiplexing is really easy to implement, look for example at the AMQP protocol used by RabbitMQ where you have similar requirements. An AMQP client can be written in an afternoon or so, and as it's pretty symmetrical, the server side should not be much more work.

1
  • Otoh, multiplexing streams over a single tcp connection introduces the problem that the individual streams become dependent on each other and can only be read in lockstep, increasing latency in case of retransmission unnecesarily.
    – Bergi
    Commented Oct 3, 2023 at 21:58
0

I know in theory this could be done in a single connection, but you could run into the problem where the client requests some information and the server would respond first with some request to the client instead of the answer. So there has to be logic to classify what the server has send, instead of just assuming that it is the answer to the request.

It seems like you need a simple messaging system, where each message has at least the following properties:

  • the message type: "request" or "reply"
  • a correlation identifier: an unique id that identifies which reply is for which request
  • the message body

This way you can have requests sent in both directions and replies can be out of order.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.