M5stickCのlwIPにTCP_QUICKACKを追加してみました

M5stickCのlwIPにTCP_QUICKACKを追加してみました

# 背景  
mqttの通信実験を行ってる際に、
publishパケットとackパケットの数が違うので、
TCP_QUICKACK有効にしてpublishパケットとackパケットの数を合わせることで
応答確認をしやすくしようと思いました  

しかし、ショックなことにlwIPにはTCP_QUICKACK設定がないことが
分かりました  
せっかくの機会なので、lwIPの勉強を兼ねて自分で追加してみました  

お願い  
導入は自己責任でお願いします  

---

# 1 TCP_QUICKACKとは  
初期設定（TCP_QUICKACK無効）においては、必要な時にACKを返します。  
TCP_QUICKACKを有効にすると、即ACKを返します。  

* TCP_QUICKACK有効時のメリット
TCPの受信ごとにACKを返すので応答速度をあげることが出来ます。  

* TCP_QUICKACK有効時のデメリット
TCPの受信ごとにACKを返すので通信量増加とTCPスタック負荷増となります。

wikipedia
https://ja.wikipedia.org/wiki/TCP%E9%81%85%E5%BB%B6ACK

---

# 2 lwIPとは  

組込用途に適した軽量TCPスタックです。  
M5stickCで採用されています。  

wikipedia
https://ja.wikipedia.org/wiki/LwIP

公式ページ
http://savannah.nongnu.org/projects/lwip/

---

# 3 準備  

## 3.1 platformIOの準備  
platformIOで開発を進めますので導入は公式ドキュメントを参照願います  

---

## 3.2 esp-idfの準備  
* M5stickCなどのESP系の、OSやデバイスドライバなどをソースコードからビルドして開発するための開発環境がesp-idfです  
* 検証時のplatformIOで採用していたEspressif32のバージョンはv3.2でした
* Espressif32のv3.2のesp-idfはv3.3系となります
* そのため、windowsにesp-idfのv3.3系の開発環境を構築します  

今回導入するv3.3.5のドキュメントにしたがって進めます
https://docs.espressif.com/projects/esp-idf/en/v3.3.5/get-started/index.html

### 3.2.1 esp-idf-toolsのインストール

#### 3.2.1.1 esp-idf-toolsをダウンロード  

[ダウンロード先](https://dl.espressif.com/dl/esp-idf/?idf=4.4)から
esp-idf-tools-setup-online-2.9.exeをダウンロードします

#### 3.2.2.2 ライセンス認証  

![認証.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/48c4c989-4fdf-9dfa-b243-68c4e5d688e7.gif)

#### 3.2.2.3 インストール環境のチェック  

![チェック.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/d024e0e3-d92a-8634-9539-5f42892b0bed.gif)

#### 3.2.2.4 esp-idfの取得  

![edfの取得.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/cd0b6c93-36b4-7a0c-3e93-eef4ffb39ec9.gif)

#### 3.2.2.5 esp-idfのバージョン選択  

![バージョン.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/14c92552-ef66-b539-fda4-0c7cb8e4bec9.gif)

#### 3.2.2.6 esp-idfのインストール先の設定  

![インストール先.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/c8284615-9757-97e6-8b61-bf310a8f1e89.gif)

#### 3.2.2.7 開発環境の設定  
私はeclipseを使わないので選択を外しています

![開発環境.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/26c960ad-c256-1ffc-4954-bfe74c2389ac.gif)

#### 3.2.2.8 インストール開始
しばらく待つと終わります
準備はこれで完了です

![インストール開始.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/31a320f3-fc34-ef88-0545-42820ec9589f.gif)

---

# 4 コードの変更内容  

## 4.1 esp-idf  

### 4.1.1 TCP_QUICKACKのdefineを追加します  

変更ファイル  
\esp-idf\components\lwip\lwip\src\include\lwip\socket.h

```diff

#define TCP_NODELAY    0x01    /* don't delay send to coalesce packets */  
#define TCP_KEEPALIVE  0x02    /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */  
#define TCP_KEEPIDLE   0x03    /* set pcb->keep_idle Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */  
#define TCP_KEEPINTVL  0x04    /* set pcb->keep_intvl Use seconds for get/setsockopt */  
#define TCP_KEEPCNT    0x05    /* set pcb->keep_cnt Use number of probes sent for get/setsockopt */ 
+ #define TCP_QUICKACK   0x06    /* set pcb->quickack get/setsockopt */
#endif /* LWIP_TCP */  
```

### 4.1.2 quickack設定用の変数定義を追加します  

変更ファイル  
\esp-idf\components\lwip\lwip\src\include\lwip\tcp.h

```diff

  /* KEEPALIVE counter */
  u8_t keep_cnt_sent;
+
+  u32_t quickack;
+
 #if LWIP_WND_SCALE
  u8_t snd_scale;
  u8_t rcv_scale;
 #endif
```

### 4.1.3 quickack設定用の変数を初期化します  

変更ファイル  
\esp-idf\components\lwip\lwip\src\core\tcp.c

変更関数  
tcp_alloc  

```diff

 #if LWIP_TCP_KEEPALIVE
    pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT;
    pcb->keep_cnt   = TCP_KEEPCNT_DEFAULT;
 #endif /* LWIP_TCP_KEEPALIVE */
+
+    pcb->quickack = 0;
+
  }
  return pcb;
 }
```

### 4.1.4 TCP_QUICKACKのオプション取得を追加します  

変更ファイル  
\esp-idf\components\lwip\lwip\src\api\socket.c

変更関数  
lwip_getsockopt_impl  

```diff

    case TCP_KEEPALIVE:
      *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle;
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) = %d\n", s, *(int *)optval));
      break;
+
+    case TCP_QUICKACK:
+      *(int*)optval = sock->conn->pcb.tcp->quickack;
+      break;
+
 #if LWIP_TCP_KEEPALIVE
     case TCP_KEEPIDLE:
```

### 4.1.5 TCP_QUICKACKのオプション設定を追加します  

変更ファイル  
\esp-idf\components\lwip\lwip\src\api\socket.c

変更関数  
lwip_setsockopt_impl  

```diff

        case TCP_KEEPALIVE:
      sock->conn->pcb.tcp->keep_idle = (u32_t)(*(const int*)optval);
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n", s, sock->conn->pcb.tcp->keep_idle));
      break;
+
+    case TCP_QUICKACK:
+      sock->conn->pcb.tcp->quickack = (u32_t)(*(const int*)optval);
+      break;
+
 #if LWIP_TCP_KEEPALIVE
    case TCP_KEEPIDLE:
```

### 4.1.6 quickack有効時の振る舞いを追加します  

変更ファイル  
\esp-idf\components\lwip\lwip\src\core\tcp_in.c

変更関数  
tcp_receive  

```diff

 #endif /* TCP_QUEUE_OOSEQ */
-
-        /* Acknowledge the segment(s). */
-        tcp_ack(pcb);
+        if( pcb->quickack!= 0 ) {
+          tcp_ack_now(pcb);
+        } else {
+          /* Acknowledge the segment(s). */
+          tcp_ack(pcb);
+        }
+
 #if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS
```

### 4.1.7 ビルドオプションの変更します  

#### 4.1.7.1 ESP-IDF 3.3 CMDのコマンドプロンプトを開きます  

#### 4.1.7.2 ビルドプロジェクトに移動します  

```
cd example\get-start\hello-world
```
※例としてhello-worldを選んでいます

#### 4.1.7.3 メニューを開きます  

```
idf.py menuconfig
```

![menu.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/829ed771-a365-73eb-b944-e2f6f61df50a.gif)

#### 4.1.7.4 ビルドオプションを設定します  

1) Component config -->  
![menu_1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/c957522e-3013-c369-0748-83771a69f161.gif)

2) LWIP-->  
![menu_lwip.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/af9a66df-470e-b586-877d-4a4c54c0cd7c.gif)

3) [ ]Enable SO_RCVBUF optionを[*]Enable SO_RCVBUF optionにします  
![menu_so_rcvbuf.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/61171424-8a27-dee9-0fcd-5d125a599d4e.gif)

4) saveして終了します

### 4.1.8 ビルドします  

```
idf.py build  
```

エラーがなければ完了です    

---

## 4.2 実験用プロジェクト  

### 4.2.1 TCP_QUICKACKのdefineを追加  

変更ファイル  
platformIOのインストール先\platformio\packages\framework-arduinoespressif32\tools\sdk\include\lwip\lwip\socket.h

```diff

#define TCP_NODELAY    0x01    /* don't delay send to coalesce packets */  
#define TCP_KEEPALIVE  0x02    /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */  
#define TCP_KEEPIDLE   0x03    /* set pcb->keep_idle Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */  
#define TCP_KEEPINTVL  0x04    /* set pcb->keep_intvl Use seconds for get/setsockopt */  
#define TCP_KEEPCNT    0x05    /* set pcb->keep_cnt Use number of probes sent for get/setsockopt */ 
+ #define TCP_QUICKACK   0x06    /* set pcb->quickack get/setsockopt */
#endif /* LWIP_TCP */  
```

### 4.2.2 quickack設定用の変数定義を追加  

変更ファイル  
platformIOのインストール先platformio\packages\framework-arduinoespressif32\tools\sdk\include\lwip\lwip\tcp.h

```diff

  /* KEEPALIVE counter */
  u8_t keep_cnt_sent;
+
+  u32_t quickack;
+
 #if LWIP_WND_SCALE
  u8_t snd_scale;
  u8_t rcv_scale;
 #endif
```

### 4.2.3 ライブラリファイルを更新します

念のため、上書きする間にライブラリをバックアップしておくとよいかと思います  

コピー元  
esp-idf\examples\get-started\hello_world\build\esp-idf\lwip\liblwip.a

コピー先  
platformio\packages\framework-arduinoespressif32\tools\sdk\lib\liblwip.a

---

# 5 使い方  

~~~
設定値取得  
    httpsClient.getOption(TCP_QUICKACK,&getval);

設定値更新
    setval = 1; /* 有効 */
    httpsClient.setOption(TCP_QUICKACK,&setval);

    setval = 0; /* 無効 */
    httpsClient.setOption(TCP_QUICKACK,&setval);
~~~

---

# 6 サンプル  

MQTTのsubscriberのプロジェクトにおいて
TCP_QUICKACK設定を切り替えています  

~~~c:pubsub_test.c
#include <M5StickC.h>
#include <PubSubClient.h>
#include <WiFi.h>
#include <LovyanGFX.hpp>
#include <lwip/sockets.h>

// Wi-FiのSSID
const char *ssid = "****";
// Wi-Fiのパスワード
const char *password = "****";
// MQTTの接続先のIP
const char *endpoint = "192.168.0.22";
// MQTTのポート
const int port = 1883;

// デバイスID
const char *deviceID = "M5Stickc_1";  // デバイスIDは機器ごとにユニークにします
// メッセージを知らせるトピック
const char *pubTopic = "/pub/M5Stickc_1";
// メッセージを待つトピック
const char *subTopic = "/sub/M5Stickc_1";
 
////////////////////////////////////////////////////////////////////////////////

static LGFX lcd;

WiFiClient httpsClient;
PubSubClient mqttClient(httpsClient);

int qa = 0;
int setval = 1;
char subMessage[128];
void mqttCallback (char* topic, byte* payload, unsigned int length) {
    int res;
    int getval;
    Serial.print("Received. topic=");
    Serial.println(topic);

    httpsClient.getOption(TCP_QUICKACK,&getval);
    Serial.printf("get TCP_QUICKACK %d/%d\n",getval,qa);

    for (int i=0; i < length; i++) {
      subMessage[i] = (char)payload[i];
    }
    Serial.println(subMessage);

    res = httpsClient.setOption(TCP_QUICKACK,&setval);
    if (res != 0 ) {
        Serial.printf("set TCP_QUICKACK error %d\n",res);
    }

    // ディスプレイへ受信内容を表示
    lcd.setCursor(0,40);
    lcd.printf("RX: %s", subMessage );
}

void connectMQTT() {
    while (!mqttClient.connected()) {
        if (mqttClient.connect(deviceID)) {
            httpsClient.setNoDelay(true);   // disable nagle
            Serial.println("MQTT Connected.");
            int qos = 0;
            mqttClient.subscribe(pubTopic, qos);
            Serial.println("Subscribed.");
        } else {
            Serial.printf("Failed. Error state=%d\n",mqttClient.state());
            // Wait 5 seconds before retrying
            delay(5000);
        }
    }
}

void setup() {
    Serial.begin(115200);
     
    // Initialize the M5Stack object
    M5.begin();
 
    lcd.init();                       // 初期化

    // START
    lcd.fillScreen(BLACK);
    lcd.setCursor(10, 10);
    lcd.setTextColor(WHITE);
    lcd.setTextSize(1);
    lcd.printf("START");
     
    // Start WiFi
    Serial.println("Connecting to ");
    Serial.print(ssid);
    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print("*");
    }

    // WiFi Connected
    Serial.println("\nWiFi Connected.");
    lcd.setCursor(10, 40);
    lcd.setTextColor(WHITE);
    lcd.printf("WiFi Connected.");
     
    mqttClient.setServer(endpoint, port);
    mqttClient.setCallback(mqttCallback);
    
    connectMQTT();

}

char pubMessage[128];
int count = 0;

void mqttLoop(void) {
    if (!mqttClient.connected()) {
        connectMQTT();
    }
    mqttClient.loop();
}

void loop() {

    mqttLoop();

    if(M5.BtnA.wasPressed() != 0 ) {
        Serial.println("pressA");
        lcd.println("pressA");

        sprintf(pubMessage, "{\"count qa\": %d}", count++);
        Serial.print("Publishing message to topic qa");

        Serial.println(pubTopic);
        Serial.println(pubMessage);

        mqttClient.publish(pubTopic, pubMessage, 0, MQTTQOS0);

        Serial.println("Published.");
    }

    if(M5.BtnB.wasPressed() != 0 ) {
        setval ++;
        setval %= 2;
        Serial.printf("pressB %d\n",setval);
        lcd.printf("pressB %d\n",setval);
    }

    M5.update();
    delay(10);
}

~~~

---

# 7 結果  

pubslishパケットとACKパケットの数が一致するか確認します

凡例

| 記号   | 説明  |
| -      | -    |
| T      | 送信  |
| TS     | レスポンスがまとめられた送信 |
| R???   | 送信???パケットのACKレスポンス |
| -      | 通信エラーパケット |

* TCP_QUICKACK無効

T 18個
R 12個

QUICKACK無効のため、6個のACKパケットを減らしています  


|	| No.	| Time	| Source	| Destination	| Protocol |	Length	| Sequence number |	Acknowledgment Number |	Info |
|-  | -     | -     | -         | -             | -        | -          | -               | -                     | -    |
TS|309|0|192.168.0.21|192.168.0.22|MQTT|60|1|1|Ping Request
T|310|0.000260834|192.168.0.22|192.168.0.21|MQTT|56|1|3|Ping Response
R310|311|0.012788982|192.168.0.21|192.168.0.22|TCP|60|3|3|55272  >  1883 [ACK] Seq=3 Ack=3 Win=5700 Len=0
T|527|9.395390509|192.168.0.22|192.168.0.21|MQTT|88|3|3|Publish Message [/pub/M5Stickc_1]
TS|528|0.000193334|192.168.0.22|192.168.0.21|MQTT|122|37|3|Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1]
T|529|0.000740001|192.168.0.22|192.168.0.21|MQTT|292|105|3|Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1]
R527|533|0.186260289|192.168.0.21|192.168.0.22|TCP|60|3|37|55272  >  1883 [ACK] Seq=3 Ack=37 Win=5666 Len=0
T|539|0.248317435|192.168.0.22|192.168.0.21|TCP|360|37|3|[TCP Retransmission] 1883  >  55272 [PSH, ACK] Seq=37 Ack=3 Win=64184 Len=306
R529|541|0.040337001|192.168.0.21|192.168.0.22|TCP|60|3|343|55272  >  1883 [ACK] Seq=3 Ack=343 Win=5360 Len=0
T|676|4.413271966|192.168.0.22|192.168.0.21|MQTT|88|343|3|Publish Message [/pub/M5Stickc_1]
T|680|0.033683863|192.168.0.22|192.168.0.21|MQTT|88|377|3|Publish Message [/pub/M5Stickc_1]
R676|690|0.069251585|192.168.0.21|192.168.0.22|TCP|60|3|377|55272  >  1883 [ACK] Seq=3 Ack=377 Win=5326 Len=0
T|691|7.2812E-05|192.168.0.22|192.168.0.21|MQTT|224|411|3|Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1]
R680|692|0.007991421|192.168.0.21|192.168.0.22|TCP|60|3|411|55272  >  1883 [ACK] Seq=3 Ack=411 Win=5292 Len=0
T|695|0.000345938|192.168.0.22|192.168.0.21|MQTT|88|581|3|Publish Message [/pub/M5Stickc_1]
R691|696|0.001326097|192.168.0.21|192.168.0.22|TCP|60|3|581|55272  >  1883 [ACK] Seq=3 Ack=581 Win=5122 Len=0
T|700|0.008312879|192.168.0.22|192.168.0.21|MQTT|88|615|3|Publish Message [/pub/M5Stickc_1]
R695|701|0.002579849|192.168.0.21|192.168.0.22|TCP|60|3|615|55272  >  1883 [ACK] Seq=3 Ack=615 Win=5088 Len=0
R700|702|0.004276674|192.168.0.21|192.168.0.22|TCP|60|3|649|55272  >  1883 [ACK] Seq=3 Ack=649 Win=5054 Len=0
T|705|0.009433663|192.168.0.22|192.168.0.21|MQTT|88|649|3|Publish Message [/pub/M5Stickc_1]
R705|710|0.159095029|192.168.0.21|192.168.0.22|TCP|60|3|683|55272  >  1883 [ACK] Seq=3 Ack=683 Win=5020 Len=0
TS|715|0.421771862|192.168.0.21|192.168.0.22|MQTT|60|3|683|Ping Request
T|716|0.000274323|192.168.0.22|192.168.0.21|MQTT|56|683|5|Ping Response
R716|719|0.062750375|192.168.0.21|192.168.0.22|TCP|60|5|685|55272  >  1883 [ACK] Seq=5 Ack=685 Win=5018 Len=0
TS|820|4.443223995|192.168.0.22|192.168.0.21|MQTT|88|685|5|Publish Message [/pub/M5Stickc_1]
TS|823|0.005977771|192.168.0.22|192.168.0.21|MQTT|88|719|5|Publish Message [/pub/M5Stickc_1]
TS|824|0.000173073|192.168.0.22|192.168.0.21|MQTT|88|753|5|Publish Message [/pub/M5Stickc_1]
T|825|0.000124115|192.168.0.22|192.168.0.21|MQTT|122|787|5|Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1]
-|834|0.285642652|192.168.0.22|192.168.0.21|TCP|224|685|5|[TCP Retransmission] 1883  >  55272 [PSH, ACK] Seq=685 Ack=5 Win=64182 Len=170
R825|836|0.134010607|192.168.0.21|192.168.0.22|TCP|60|5|855|55272  >  1883 [ACK] Seq=5 Ack=855 Win=4848 Len=0
T|837|0.000119688|192.168.0.22|192.168.0.21|MQTT|224|855|5|Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1]
-|839|0.103405551|192.168.0.21|192.168.0.22|TCP|60|5|855|[TCP Dup ACK 836#1] 55272  >  1883 [ACK] Seq=5 Ack=855 Win=4848 Len=0
R837|840|0.000153907|192.168.0.21|192.168.0.22|TCP|60|5|1025|55272  >  1883 [ACK] Seq=5 Ack=1025 Win=4678 Len=0

* TCP_QUICKACK有効  

T 20個
R 20個

TCPとACKパケットが同じなのでQUICKACKが効いていると思います  

| | No. | Time | Source | Destination | Protocol | Length | Sequence number | Acknowledgment Number | Info
 -  | -     | -     | -         | -             | -        | -          | -               | -                     | -    |
 | 372 | 0 | 192.168.0.21 | 192.168.0.22 |MQTT|60|1|1|Ping Request
T|373|0.00025849|192.168.0.22|192.168.0.21|MQTT|56|1|3|Ping Response
R373|374|0.009280068|192.168.0.21|192.168.0.22|TCP|60|3|3|55272  >  1883 [ACK] Seq=3 Ack=3 Win=4672 Len=0
T|732|11.823577702|192.168.0.22|192.168.0.21|MQTT|88|3|3|Publish Message [/pub/M5Stickc_1]
T|735|0.018673781|192.168.0.22|192.168.0.21|MQTT|88|37|3|Publish Message [/pub/M5Stickc_1]
R732|749|0.068378345|192.168.0.21|192.168.0.22|TCP|60|3|37|55272  >  1883 [ACK] Seq=3 Ack=37 Win=4638 Len=0
T|750|7.5469E-05|192.168.0.22|192.168.0.21|MQTT|224|71|3|Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1]
R735|751|0.000151615|192.168.0.21|192.168.0.22|TCP|60|3|71|55272  >  1883 [ACK] Seq=3 Ack=71 Win=4604 Len=0
R750|754|0.011953041|192.168.0.21|192.168.0.22|TCP|60|3|241|55272  >  1883 [ACK] Seq=3 Ack=241 Win=4434 Len=0
T|755|4.3333E-05|192.168.0.22|192.168.0.21|MQTT|88|241|3|Publish Message [/pub/M5Stickc_1]
R755|756|0.004809748|192.168.0.21|192.168.0.22|TCP|60|3|275|55272  >  1883 [ACK] Seq=3 Ack=275 Win=4400 Len=0
T|759|0.005588759|192.168.0.22|192.168.0.21|MQTT|88|275|3|Publish Message [/pub/M5Stickc_1]
R759|760|0.004332351|192.168.0.21|192.168.0.22|TCP|60|3|309|55272  >  1883 [ACK] Seq=3 Ack=309 Win=4366 Len=0
T|763|0.024022645|192.168.0.22|192.168.0.21|MQTT|88|309|3|Publish Message [/pub/M5Stickc_1]
R763|764|0.008477879|192.168.0.21|192.168.0.22|TCP|60|3|343|55272  >  1883 [ACK] Seq=3 Ack=343 Win=4332 Len=0
T|877|3.03367422|192.168.0.21|192.168.0.22|MQTT|60|3|343|Ping Request
T|878|0.000230417|192.168.0.22|192.168.0.21|MQTT|56|343|5|Ping Response
R877|879|0.004368966|192.168.0.21|192.168.0.22|TCP|60|5|345|55272  >  1883 [ACK] Seq=5 Ack=345 Win=4330 Len=0
T|975|2.106806607|192.168.0.22|192.168.0.21|MQTT|88|345|5|Publish Message [/pub/M5Stickc_1]
T|983|0.142087425|192.168.0.22|192.168.0.21|MQTT|88|379|5|Publish Message [/pub/M5Stickc_1]
R975|986|0.073340592|192.168.0.21|192.168.0.22|TCP|60|5|379|55272  >  1883 [ACK] Seq=5 Ack=379 Win=4296 Len=0
T|987|0.000123333|192.168.0.22|192.168.0.21|MQTT|326|413|5|Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1]
R983|988|0.000207657|192.168.0.21|192.168.0.22|TCP|60|5|413|55272  >  1883 [ACK] Seq=5 Ack=413 Win=4262 Len=0
T|989|0.002308858|192.168.0.21|192.168.0.22|TCP|60|5|413|[TCP Window Update] 55272  >  1883 [ACK] Seq=5 Ack=413 Win=5710 Len=0
R373|990|0.012468146|192.168.0.21|192.168.0.22|TCP|60|5|685|55272  >  1883 [ACK] Seq=5 Ack=685 Win=5438 Len=0
T|1130|4.794089045|192.168.0.22|192.168.0.21|MQTT|88|685|5|Publish Message [/pub/M5Stickc_1]
T|1133|0.015986068|192.168.0.22|192.168.0.21|MQTT|88|719|5|Publish Message [/pub/M5Stickc_1]
T|1136|0.014751431|192.168.0.22|192.168.0.21|MQTT|88|753|5|Publish Message [/pub/M5Stickc_1]
T|1139|0.015450859|192.168.0.22|192.168.0.21|MQTT|88|787|5|Publish Message [/pub/M5Stickc_1]
R1130|1149|0.065963547|192.168.0.21|192.168.0.22|TCP|60|5|719|55272  >  1883 [ACK] Seq=5 Ack=719 Win=5404 Len=0
T|1150|0.000087761|192.168.0.22|192.168.0.21|MQTT|190|821|5|Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1]
R1133|1151|0.000747188|192.168.0.21|192.168.0.22|TCP|60|5|753|55272  >  1883 [ACK] Seq=5 Ack=753 Win=5370 Len=0
R1136|1152|0.001131096|192.168.0.21|192.168.0.22|TCP|60|5|787|55272  >  1883 [ACK] Seq=5 Ack=787 Win=5336 Len=0
R1139|1153|0.000174479|192.168.0.21|192.168.0.22|TCP|60|5|821|55272  >  1883 [ACK] Seq=5 Ack=821 Win=5302 Len=0
R1150|1154|0.002439536|192.168.0.21|192.168.0.22|TCP|60|5|957|55272  >  1883 [ACK] Seq=5 Ack=957 Win=5166 Len=0
T|1157|0.008647149|192.168.0.22|192.168.0.21|MQTT|88|957|5|Publish Message [/pub/M5Stickc_1]
R1157|1158|0.004542768|192.168.0.21|192.168.0.22|TCP|60|5|991|55272  >  1883 [ACK] Seq=5 Ack=991 Win=5132 Len=0
T|1161|0.005588031|192.168.0.22|192.168.0.21|MQTT|88|991|5|Publish Message [/pub/M5Stickc_1]
R1161|1162|0.005189383|192.168.0.21|192.168.0.22|TCP|60|5|1025|55272  >  1883 [ACK] Seq=5 Ack=1025 Win=5098 Len=0


以上です  
![edfの取得.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/0ae122a0-2e88-7255-9b5c-2efdd255bbb6.gif)