[Tex/LaTex] Creating protocol message diagrams

diagramstikz-pgf

I would like to create small protocol message diagrams as seen in IETF documents (e.g. as in CoAP). Nice would be auto aligning depending the amount of text (bigger texts appear like in CoAP HLS)

Example:

Client  Server
  |      |
  |      |
  +----->|     Header: GET (T=CON, Code=0.01, MID=0x7d34)
  | GET  |   Uri-Path: "temperature"
  |      |
  |      |
  |<-----+     Header: 2.05 Content (T=ACK, Code=2.05, MID=0x7d34)
  | 2.05 |    Payload: "22.3 C"
  |      |

Is there some package that would help?
msc and pgf-umlsd or tikz-uml didn't look right….

Alternativly I could "hand-draw" that using TikZ.
If there's no package to help here, how would a minimal TikZ example look?

Best Answer

I think it's easy to draw some diagram like that if you start placing comments and after that use them as references to draw message interchanges.

Next code shows a minimal example. I've used matrix to create all comments and server and client labels. Of course, you don't need to use a matrix and can place them using relative positions.

The tricky part is how to align message arrows with corresponding comment first line. May be there exist better solutions but I've used \subnode command from tikzmark library. It creates an internal reference inside every comment node.

Finally it's easy to draw message interchanges with the help of intersection coordinates (|- or -|).

This is a complete code for a minimal example:

    \documentclass[tikz,border=2mm]{standalone}

    \usetikzlibrary{matrix,positioning,tikzmark}

    \begin{document}
    \begin{tikzpicture}[remember picture, % --- Dont' forget it with tikzmark ---
        comment/.style={text width=10cm, align=left},   
        font=\small\ttfamily]

    %Place `Client`, `Server` and `comment` nodes   
    \matrix{%
        \node (client) {Client}; & 
        \node (server) {Server}; & \\
        & & 
        \node[comment] (1) {\subnode{A}{Header}: 
            GET (T=CON, Code=0.01, MID=0x7d34)\\ 
            Uri-Path: "temperature"}; \\ 
        & & 
        \node[comment] (2) {\subnode{B}{Header}: 
            2.05 Content (T=ACK, Code=2.05, MID=0x7d34)\\ 
            Payload: "22.3 C"}; \\};

    %Draw vertical lines
    \draw (client) -- (client|-2.south);
    \draw (server) -- (server|-2.south);

    %Draw message interchanges
    \draw[->] (A-|client)--node[below]{GET} (A-|server) ;
    \draw[<-] (B-|client)-- node[below]{2.05} (B-|server) ;
    \end{tikzpicture}
    \end{document}

Compile previous code twice to get

enter image description here

Update

If you want to align comments around colons, you can use a tabular inside comments. In this case you have to use ampersand replacement option inside \matrix because it's necessary to have different & symbols inside tabular and matrix.

\begin{tikzpicture}[remember picture, 
    comment/.style={text width=10cm, align=left},   
    font=\small\ttfamily]

%Place `Client`, `Server` and `comment` nodes   
\matrix [ampersand replacement=\&]{%
    \node (client) {Client}; \& 
    \node (server) {Server}; \& \\
    \& \& 
    \node[comment] (1) {\begin{tabular}{r@{ }l}\subnode{A}{Header}:& 
        GET (T=CON, Code=0.01, MID=0x7d34)\\ 
        Uri-Path:& "temperature"\end{tabular}}; \\ 
    \& \& 
    \node[comment] (2) {\begin{tabular}{r@{ }l}\subnode{B}{Header}:& 
        2.05 Content (T=ACK, Code=2.05, MID=0x7d34)\\ 
        Payload:& "22.3 C"\end{tabular}}; \\};

%Draw vertical lines
\draw (client) -- (client|-2.south);
\draw (server) -- (server|-2.south);

%Draw message interchanges
\draw[->] (A-|client)--node[below]{GET} (A-|server) ;
\draw[<-] (B-|client)-- node[below]{2.05} (B-|server) ;
\end{tikzpicture}

The result is now

enter image description here

But, if you want to align all comments, it's better to put all of them inside a tabular. You can avoid using \matrix and place server and client labels after it. In order to separate different comments you can use \\[vertical distance] inside tabular.

Solution looks like:

\begin{tikzpicture}[remember picture, 
    font=\small\ttfamily]

%Place a `comment` node with all text inside a tabular  
 \node(comments) {\begin{tabular}{r@{ }l}
        \subnode{A}{Header}:& 
        GET (T=CON, Code=0.01, MID=0x7d34)\\ 
        Uri-Path:& "temperature"\\[3mm] 
       \subnode{B}{Header}:& 
        2.05 Content (T=ACK, Code=2.05, MID=0x7d34)\\ 
        Payload:& "22.3 C"\end{tabular}};

% Place `server` and `client` nodes
\node[above left=1mm and 0mm of comments] (server) {Server}; 
\node[left=5mm of server] (client) {Client}; 

%Draw vertical lines
\draw (client) -- (client|-comments.south);
\draw (server) -- (server|-comments.south);

%Draw message interchanges
\draw[->] (A-|client)--node[below]{GET} (A-|server) ;
\draw[<-] (B-|client)-- node[below]{2.05} (B-|server) ;
\end{tikzpicture}

And the result is:

enter image description here