0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Modbus/TCPを基礎から整理する

Last updated at Posted at 2026-01-10

この記事では、Modbus/TCP について以下の点を中心にまとめています。

  • TCP 502番ポートを用いた接続の考え方
  • ADU / PDU の構造とサイズ制限
  • 各ファンクションコードにおけるデータ構成
  • 1リクエストあたりの最大読み書き数の算出根拠
  • OSI 7階層・TCP/IP 4階層との対応関係

仕様書を読んでも分かりづらかった部分を、
「なぜその数になるのか」「どの層の話なのか」
という観点で整理しています。

同じように Modbus を復習したい方や、
新人・後輩に説明する立場の方の参考になれば幸いです。

1. サーバーへの接続(Modbus/TCP)

  • Modbus/TCP は TCP の 502 番ポートを使用する
  • クライアント(PLC など)は、サーバー(製品)の IP アドレス + TCP 502 番ポートへ接続する
  • サーバー側では、クライアントからの接続を許可するために、接続元アドレスのフィルタリング設定(詳細は補足をご覧ください)が必要

2. Modbus/TCP のパケット構造

Modbus/TCP では、以下のような リクエスト/レスポンス方式で通信を行う。(1 回のリクエストに対して、必ず 1 回のレスポンスが返される。)

  • クライアント → サーバー:リクエスト
  • サーバー → クライアント:レスポンス

※Modbus/TCP では、クライアントからのリクエストとサーバーからのレスポンスの両方に同じパケット形式を使用する。

用語整理(備考)

パケット(Packet)

通信でやり取りされるデータのかたまり

パケット形式(Packet Format)

通信でやり取りするデータの並び方のルール

2.1 ADU(Application Data Unit)の構成

modbus_adu.png

  • ADU内のすべての数値はビッグエンディアン形式
  • 最上位バイトがアドレスの小さい側に配置される

3. Modbus の制御対象とアドレス空間

Modbus で扱う制御対象は、ビット数とアクセス権限によって4種類に分類される。

名称 操作単位 アクセス 通し番号 アドレス範囲
コイル (Coil) 1 ビット R/W 00001~09999 0~9998
インプット (Discrete Input) 1 ビット R 10001~19999 0~9998
ホールディング・レジスタ (Holding Register) 16 ビット R/W 40001~49999 0~9998
インプット・レジスタ (Input Register) 16 ビット R 30001~39999 0~9998

製品制御における重要ポイント

  • 製品制御は主にホールディング・レジスタ(読み書き)とインプット・レジスタ(読み取り)を使用
  • 各制御対象は独立したアドレス空間を持つ
  • ファンクション実行時は通し番号ではなくアドレスを指定する

3.1 1リクエストあたりの最大読み書き数

Modbus/TCP では、ADUとPDUの最大サイズに制限があるため、1回のリクエストで読み書きできる数に上限がある。

前提条件

(※「2.1 ADU(Application Data Unit)の構成図」に記載の通り、以下の条件とする)

1 バイト = 8 ビット
ADU最大サイズ:260 バイト
MBAP Header   :7 バイト
PDU最大:253バイト
├ Function Code:1バイト
└ Data:最大252バイト
      │
      ├ Read Coils / Discrete Inputs (0x01 / 0x02)
      │   ├ リクエスト:4バイト
      │   │   - Start Address (2)
      │   │   - Quantity (2)
      │   └ レスポンス:1 + N バイト
      │       - Byte Count (1)
      │       - Coil Data (N)
      │
      ├ Read Holding / Input Registers (0x03 / 0x04)
      │   ├ リクエスト:4バイト
      │   │   - Start Address (2)
      │   │   - Quantity (2)
      │   └ レスポンス:1 + N×2 バイト
      │       - Byte Count (1)
      │       - Register Data (N×2)
      │
      ├ Write Single Coil (0x05)
      │   ├ リクエスト:4バイト
      │   │   - Output Address (2)
      │   │   - Output Value (2)
      │   └ レスポンス:4バイト
      │       - Output Address (2)
      │       - Output Value (2)
      │
      ├ Write Single Register (0x06)
      │   ├ リクエスト:4バイト
      │   │   - Register Address (2)
      │   │   - Register Value (2)
      │   └ レスポンス:4バイト
      │       - Register Address (2)
      │       - Register Value (2)
      │
      ├ Write Multiple Coils (0x0F)
      │   ├ リクエスト:5 + N バイト
      │   │   - Start Address (2)
      │   │   - Quantity (2)
      │   │   - Byte Count (1)
      │   │   - Coil Data (N)
      │   └ レスポンス:4バイト
      │       - Start Address (2)
      │       - Quantity (2)
      │
      └ Write Multiple Registers (0x10)
          ├ リクエスト:5 + N×2 バイト
          │   - Start Address (2)
          │   - Quantity (2)
          │   - Byte Count (1)
          │   - Register Data (N×2)
          └ レスポンス:4バイト
              - Start Address (2)
              - Quantity (2)




最大数の算出

Read Coils / Discrete Inputs (0x01 / 0x02)

レスポンスPDU構造:

Function Code(1) + Byte Count(1) + Coil Data(N) = 2 + Nバイト
  • 2 + N ≤ 253 → N ≤ 251バイト
  • ビット単位:251 × 8 = 2008ビット
  • 仕様上の上限:2000ビット

Write Multiple Coils (0x0F)

リクエストPDU構造:

Function Code(1) + Start Address(2) + Quantity(2) + Byte Count(1) + Coil Data(N) = 6 + Nバイト
  • 6 + N ≤ 253 → N ≤ 247バイト
  • ビット単位:247 × 8 = 1976ビット
  • 仕様上の上限:1968ビット

Read Holding / Input Registers (0x03 / 0x04)

レスポンスPDU構造:

Function Code(1) + Byte Count(1) + Register Data(N×2) = 2 + N×2バイト
  • 2 + N×2 ≤ 253 → N ≤ 125.5
  • 仕様上の上限:125レジスタ

Write Multiple Registers (0x10)

リクエストPDU構造:

Function Code(1) + Start Address(2) + Quantity(2) + Byte Count(1) + Register Data(N×2) = 6 + N×2バイト
  • 6 + N×2 ≤ 253 → N ≤ 123.5
  • 仕様上の上限:123レジスタ

まとめ表

操作 理論上の最大 仕様上の上限 制約要因
Read Coils / Discrete Inputs 2008ビット 2000ビット レスポンスPDU(251バイト)
Write Multiple Coils 1976ビット 1968ビット リクエストPDU(247バイト)
Read Holding / Input Registers 125レジスタ 125レジスタ レスポンスPDU(251バイト)
Write Multiple Registers 123レジスタ 123レジスタ リクエストPDU(247バイト)

4. サポートされるファンクション・コード

ファンクション・コード 説明 種別
Read Coils 0x01 コイルの値を読み出す オプション
Read Discrete Inputs 0x02 インプットの値を読み出す オプション
Read Holding Registers 0x03 ホールディング・レジスタの値を読み出す 必須
Read Input Registers 0x04 インプット・レジスタの値を読み出す 必須
Write Single Coil 0x05 1つのコイルに値を書き込む オプション
Write Single Register 0x06 1つのホールディング・レジスタに値を書き込む オプション
Write Multiple Coils 0x0F 複数のコイルに値を書き込む オプション
Write Multiple Registers 0x10 複数のホールディング・レジスタに値を書き込む 必須

製品制御において一般的に使用される主要ファンクション

  • 0x03:ホールディング・レジスタの読み出し(事実上必須)
  • 0x04:インプット・レジスタの読み出し(監視用途で使用)
  • 0x10:複数ホールディング・レジスタの書き込み(制御用途で使用)

補足

1. フィルタリングについて

1.1 Modbus/TCP の特性

  • 認証機能を持たない
  • 暗号化を行わない
  • TCP 502 番ポートを使用する

1.2 フィルタリングが必要な理由

  • 接続制限を行わない場合、任意の機器から TCP 502 番ポートへ接続可能となる
  • 誤操作、不正アクセス、想定外のPLCからの書き込みが発生する可能性がある

1.3 フィルタリングの考え方

  • 機器(サーバー)側で接続元IPアドレスを指定する
  • 許可したIPアドレス以外からの接続は受け付けない

1.4 フィルタリング設定の例

  • 許可するIPアドレス:192.168.1.10
  • 上記以外のIPアドレスからの接続は拒否する

2. 通信階層とModbus/TCP

2.1 OSI 7階層モデル(理論)

OSI参照モデルは通信を説明するための理論モデルである。ISO(国際標準化機構)が策定し、ベンダーごとに異なる通信方式を共通の言葉で説明することを目的とした。

階層 名称 役割
7 アプリケーション層 利用者が使う通信サービス(HTTP、FTP、Modbus等)
6 プレゼンテーション層 データ形式の変換、暗号化、文字コード
5 セッション層 通信の開始・終了、会話の管理
4 トランスポート層 信頼性のあるデータ転送、再送制御(TCP、UDP)
3 ネットワーク層 異なるネットワーク間の経路選択(IP)
2 データリンク層 同一ネットワーク内でのデータ転送制御
1 物理層 電気信号、ケーブル、物理的な接続

7階層に分けた理由

  • 通信の役割を完全に分離し、責任範囲を明確にするため
  • 各階層が独立して開発・変更できるようにするため

2.2 TCP/IP 4階層モデル(実務)

TCP/IPモデルは実装から生まれた実用的なモデルである。実際のネットワーク機器やOSはこの構造で動作している。

階層 名称 何をする層か Modbus/TCP通信での具体的処理 プロトコル例
4 アプリケーション層 何をしたいか Modbusコマンドの生成と解釈(ファンクションコード03:レジスタ読み取り等) HTTP, SMTP, FTP, Modbus/TCP
3 トランスポート層 確実に届ける TCP接続の確立(ポート502)、データの分割・再構成、到達確認、再送制御 TCP, UDP
2 インターネット層 どこに届ける 送信元IP(PLC)→ 送信先IP(サーバー)へのパケット転送、ルーティング IP, ICMP
1 ネットワークインターフェース層 物理的に流す Ethernetフレームとして物理的にデータ送信、MACアドレス処理 Ethernet, Wi-Fi

4階層にまとめた理由

  • OSI の 7・6・5 層はアプリケーション内部で自然に処理される
  • OSI の 2・1 層はドライバレベルで一体として扱われる
  • 実装に即したシンプルな構造の方が理解しやすい

2.3 OSI → TCP/IP 対応関係

modbus.png


2.4 サーバー・クライアント通信フロー

TCP接続の確立から切断まで
(3ウェイハンドシェイク + データ転送 + 4ウェイハンドシェイク)

tcp.png

フロー説明

フェーズ 処理 説明
接続確立 ① SYN クライアントがTCP接続を要求。
初期シーケンス番号(SEQ)を通知し、以降この番号からバイト単位で番号を振って送信することを宣言 例:SEQ=100の場合、「これから送る最初のデータの番号が100です」**と相手に知らせる
② SYN + ACK サーバーが接続を受諾。
自分の初期SEQを通知し、クライアントのSEQ+1をACKで確認
③ ACK クライアントがサーバーのSEQ+1をACKで確認。
双方がSEQ/ACKを共有し、TCP接続が確立(3ウェイハンドシェイク完了)
データ転送 ④ リクエスト クライアントがModbus/TCPリクエストを送信。
TCPはデータを分割し、SEQを付与して送信
⑤ ACK サーバーが受信したデータのSEQを確認し、次に受信したい番号をACKで通知
⑥ レスポンス サーバーがModbus処理結果をTCPで返送。
レスポンスにもサーバー側のSEQが付与される
⑦ ACK クライアントが受信完了をACKで通知。
再送が不要であることを確認
接続切断 ⑧ FIN クライアントが「これ以上送信するデータがない」ことを通知(FINはSEQを1消費)
⑨ ACK サーバーがFINを受信し、SEQ+1をACKで確認
⑩ FIN サーバーも送信完了を通知
⑪ ACK クライアントがFINを確認し、TCP接続が完全に終了(4ウェイハンドシェイク完了)
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?