The Problem Space

BEEP works for a large class of application protocols.

However, you should always use the right tool for the right job. Before you start using BEEP for a project, you should ask yourself whether your application protocol is a good fit for either the email or Web models.

Dave Crocker, one of the Internet’s progenitors, suggests that network applications can be broadly distinguished by five operational characteristics:

  • Server push or client pull

  • Synchronous (interactive) or asynchronous (batch)

  • Time-assured or time-insensitive

  • Best-effort or reliable

  • Stateful or stateless

For example:

  • The World Wide Web is a pull, synchronous, time-insensitive, reliable, stateless service.

  • Internet mail is a push, asynchronous, time-insensitive, best-effort, stateless service.

This is a pretty useful taxonomy.

So, your first step is to see whether either of these existing infrastructures meet your requirements. It’s easiest to start by asking if your application can reside on top of email. Typically, the unpredictable latency of the Internet mail infrastructure raises the largest issues; however, in some cases it’s a non-issue. For example, in the early 90s, some of the earliest business-to-business exchanges were operated over email (e.g., USC/ISI’s FAST project). If you can find a good fit between your application and Internet email, use it!

More likely, though, you’ll be tempted to use the Web infrastructure, and there are a lot of awfully good reasons to do so. After all, when you use HTTP:

  • There’s lots of tools (libraries, servers, etc.) to choose from.

  • It’s easy to prototype stuff.

  • There’s already a security model.

  • You can traverse firewalls pretty easily.

All of this boils down to one simple fact: it is pretty easy to deploy things in the Web infrastructure. The real issue is whether you can make good use of this infrastructure.

HTTP was originally developed for retrieving documents in a LAN environment, so HTTP’s interaction model is optimized for that application. Accordingly, in HTTP:

  • Each session consists of a single request/response exchange.

  • The computer that initiates the session is also the one that initiates the request.

What needs to be emphasized here is that this is a perfectly fine interaction model for HTTP’s target application, as well as many other application domains.

The problem arises when the behavior of your application protocol doesn’t match this interaction model. In this case, there are two choices: make use of HTTP’s extensibility features, or simply make do. Obviously, each choice has some drawbacks. The problem with using HTTP’s extensibility features is that it pretty much negates the ability to use the existing HTTP infrastructure; the problem with “just making do” is that you end up crippling your protocol. For example, if your application protocol needs asynchronous notifications, you’re out of luck.

A second problem arises due to “the law of codepaths.” The HTTP 1.1 specification RFC 2616 is fairly rigorous. Even so, few implementors take the time to think out many of the nuances of the protocol. For example, the typical HTTP transaction consists of a small request, which results in a (much) larger response. Talk to any engineer who’s worked on a browser and they’ll tell you this is “obvious.” So, what happens when the “obvious” doesn’t happen?

Some time ago, folks wanted a standardized protocol for talking to networked printers. The result was something called the Internet Printing Protocol (IPP, RFC 2565). IPP sits on top of HTTP. At this point, the old “obvious” thing (small request, big response) gets replaced with the new “obvious” thing—the request contains an arbitrarily large file to be printed, and the response contains this tiny little status indication. A surprising amount of HTTP software doesn’t handle this situation particularly gracefully (i.e., long requests get silently truncated). The moral is that even though HTTP’s interaction model doesn’t play favorites with respect to lengthy requests or responses, many HTTP implementors inadvertently make unfortunate assumptions.

A third problem deals with the unitary relationship between sessions and exchanges. If a single transaction needs to consist of more than one exchange, it has to be spread out over multiple sessions. This introduces two issues:

  • In terms of stateful behavior, the server computer has to be able to keep track of session state across multiple connections, imposing a significant burden both on the correctness and implementation of the protocol (e.g., to properly handle timeouts).

  • In terms of performance, TCP isn’t designed for dealing with back-to-back connections—there’s a fair amount of overhead and latency involved in establishing a connection. This is also true for the security protocols that layer on top of TCP.

HTTP 1.1 begins to address these issues by introducing persistent connections that allow multiple exchanges to occur serially over a single connection, but still the protocol lacks a session concept. In practice, implementors try to bridge this gap by using “cookies” to manage session state, which introduces ad-hoc (in)security models that often result in security breakdowns (as a certain Web-based email service provider found out).

This brings us to a more general fourth problem: although HTTP has a security model, it predates SASL. From a practical perspective, what this means is that it’s very difficult to add new security protocols to HTTP. Of course, that may not be an issue for you.

If you can find a good fit between your application and the Web infrastructure, use it! (For those interested in a more architectural perspective on the reuse of the Web infrastructure for new application protocols, consider RFC 3205.)

Okay, so we’ve talked about both the email and Web infrastructures, and we’ve talked about what properties your application protocol needs to have in order to work well with them. So, if there isn’t a good fit between either of them and your application protocol, what about BEEP?

BEEP’s interaction model is pretty simple, with the following three properties:

  • Each session consists of one or more request/response exchanges.

  • Either computer can initiate requests or notifications.

  • It’s connection-oriented.

By using BEEP, you get an amortization effect with respect to the cost of connection establishment and state management. This is largely derived from the first property. Similarly, the second property gives BEEP its ability to support either peer-to-peer or client-server interactions. What we really need to explain is the connection-oriented part.

To begin, all three of the interaction models we’ve looked at (BEEP, email, and the Web) are connection-oriented. (Although email may get delivered out of order, the commands sent over each email “hop” are processed in an ordered, reliable fashion.) The connection-oriented model is the most commonly used for application protocols, but it does introduce some restrictions.

A connection-oriented interaction model means that data is delivered reliably and in the same order as it was sent. If you don’t require ordered, reliable delivery, you don’t need a connection-oriented interaction model. For example, Internet telephony applications don’t fit this model, nor do traditional multicast applications.

So, BEEP is suitable for unicast application protocols (two computers are talking to each other). However, not all unicast applications need a connection-oriented model—for example, the Domain Name System manages name-to-address resolutions just fine without it. In fact, if your protocol is able to limit each session to exactly one request/response exchange with minimalist reliability requirements, and also limit the size of each message to around 65K octets, then it’s probably a good candidate for using UDP instead.

Get BEEP: The Definitive Guide now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.