Как использовать graphviz нарисовать диаграмму инкапсуляции данных TCP/IP?

Я пытаюсь использовать Graphviz, чтобы нарисовать диаграмму инкапсуляции данных TCP/IP в классической книге Стивенса по TCP/IP.

диаграмма

Диаграмма кажется не стандартной компьютерной графикой. Мои вопросы:

  1. как выровнять вправо?
  2. Как отметить размер ниже каждой записи (т.е. 14 в заголовке IP, 20 в TCP)?
  3. как нарисовать край как |<----------- 46 to 1500 bytes ---------->| и положить его ниже какого-то узла?

Может ли графвиз нарисовать это? Если так, то как? Заранее спасибо.

1 ответ

  1. Для выравнивания я использовал прямые края (splines=false) и указание того, из какого угла узла они исходят и в какой угол другого узла они входят ( компасные точки ).
  2. Для создания надписей под словами я использовал HTML-метку с двухстрочной таблицей, во второй строке сделал невидимыми нижние границы и границы с левой и правой сторон, установив атрибутsides="T"(Tозначает верхнюю границу).
  3. Для рисования края, как|<----------- 46 to 1500 bytes ---------->|, я использовал уменьшение ширины узла (width=.01) и невидимые узлы и ребра, их можно найти в скрипте ниже по атрибутуstyle=invis. Вот небольшой пример с окрашенными в красный цвет элементами, которые не видны на финальном изображении:

Graphviz может его нарисовать (см. пример ниже), но, как ответили в комментариях выше, быстрее будет использовать графический редактор.

Скрипт:

      digraph TCP_IP_diagram {
    label=<<FONT><B>Figure 1.7 </B> Encapsulation of data as it goes down the protocol stack.</FONT>>
    nodesep=0
    ranksep=.1
    splines=false
    
    edge[style=dashed]
    node[shape=box height=.6]
    
    // NODES ------------------------------------
    
    table_0 [margin=0 shape=none label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
    <TR><TD PORT="f0" HEIGHT="40" FIXEDSIZE="TRUE">user data</TD></TR>
    </TABLE>>]
    
    inv_0 [shape=point style=invis]
    
    table_1 [margin=0 shape=none label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
    <TR>
        <TD PORT="f0">Appl<BR/>header</TD>
        <TD PORT="f1">user data</TD>
    </TR>
    </TABLE>>]
    
    inv_00 [shape=point style=invis]
    
    table_2 [margin=0 shape=none label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
    <TR>
        <TD PORT="f0">TCP<BR/>header</TD>
        <TD PORT="f1"> application data</TD>
    </TR>
    </TABLE>>]
    
    {
        rank=same;
        "TCP segment" [shape=plaintext]
        inv_1 [shape=point height=.01]
        inv_2 [shape=point height=.01]
    }
    
    table_3 [margin=0 shape=none label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
    <TR>
        <TD PORT="f0">IP<BR/>header</TD>
        <TD>TCP<BR/>header</TD>
        <TD PORT="f1"> application data</TD>
    </TR>
    </TABLE>>]
    
    {
        rank=same;
        "IP datagram" [shape=plaintext]
        inv_3 [shape=point height=.01]
        inv_4 [shape=point height=.01]
    }
    
    table_4 [margin=0 shape=none label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
    <TR>
        <TD PORT="f0">Ethernet<BR/>header</TD>
        <TD>IP<BR/>header</TD>
        <TD>TCP<BR/>header</TD>
        <TD> application data</TD>
        <TD PORT="f1">Ethernet<BR/>trailer</TD>
    </TR>
    <TR>
        <TD SIDES="T">14</TD>
        <TD SIDES="T">20</TD>
        <TD SIDES="T">20</TD>
        <TD SIDES="T"></TD>
        <TD SIDES="T">4</TD>
    </TR>
    </TABLE>>]
    
    {
        rank=same;
        "Ethernet frame" [shape=plaintext]
        inv_5 [shape=box height=.4 width=.01 label=""]
        inv_6 [shape=box height=.4 width=.01 label=""]
    }
    
    {
        rank=same;
        "46 to 1500 bytes" [shape=plaintext]
        inv_7 [shape=box height=.4 width=.01 label=""]
        inv_8 [shape=box height=.4 width=.01 label=""]
    }
    
    table_5 [margin=0 shape=none label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
    <TR><TD BORDER="4" PORT="f0" SIDES="T">Ethernet</TD></TR>
    </TABLE>>]
    
    morespace [style=invis shape=plain]
    
    // EDGES ------------------------------------
    
    table_0:f0:se -> table_1:f1:ne
    table_0:f0:sw -> table_1:f1:nw
    table_0 -> inv_0 [style=invis]
    inv_0 -> table_1 [style=invis]
    
    table_1:f0:sw -> table_2:f0:ne
    table_1:f1:se -> table_2:f1:ne
    
    table_1 -> inv_00 [style=invis]
    inv_00 -> table_2 [style=invis]
    
    table_2 -> "TCP segment" [style=invis]
    table_2:f0:sw -> inv_1 [arrowhead=none]
    table_2:f1:se -> inv_2 [arrowhead=none]
    
    inv_1 -> table_3:f0:ne
    inv_2 -> table_3:f1:ne
    
    "TCP segment" -> inv_1 [weight=0 style=solid]
    "TCP segment" -> inv_2 [weight=0 style=solid]
    
    table_3 -> "IP datagram" [style=invis]
    table_3:f0:sw -> inv_3 [arrowhead=none]
    table_3:f1:se -> inv_4 [arrowhead=none]
    
    "IP datagram" -> inv_3 [weight=0 style=solid]
    "IP datagram" -> inv_4 [weight=0 style=solid]
    
    inv_3 -> table_4:f0:ne [style=dashed]
    inv_4 -> table_4:f1:nw
    
    table_4 -> "Ethernet frame" [style=invis]
    table_4:f0:sw -> inv_5 [style=invis]
    table_4:f1:se -> inv_6 [style=invis]
    "Ethernet frame" -> inv_5 [weight=0 style=solid]
    "Ethernet frame" -> inv_6 [weight=0 style=solid]

    "Ethernet frame" -> "46 to 1500 bytes" [style=invis]
    table_4:f0:se -> inv_7 [style=invis]
    table_4:f1:sw -> inv_8 [style=invis]
    "46 to 1500 bytes" -> inv_7 [weight=0 style=solid]
    "46 to 1500 bytes" -> inv_8 [weight=0 style=solid]
    
    "46 to 1500 bytes" -> morespace [style=invis]
    
    {
        edge [minlen=2]
        "application" -> "TCP" -> "IP" -> "Ethernet\ndriver"
    }
    "Ethernet\ndriver" -> table_5:f0 [style=solid arrowhead=none]
    
    // OTHER RANKS ------------------------------------
    
    {rank=same;"application";inv_0}
    {rank=same;table_4;table_5}
}

Результат:

Другие вопросы по тегам