curl -v を一度実行すると、普段ブラウザが隠している通信の中身がそのまま画面に出ます。GET / HTTP/1.1 という1行、Host: というヘッダ、返ってくる HTTP/1.1 200 OK。この決まりきった並びがプロトコルの実体です。この記事では、プロトコルを構文・意味・タイミングの3要素として定義し直したうえで、手元で実行できるコマンドから実際の往復を読む手順、現行仕様がどのRFCに書かれているか、IANAが管理するポート番号の3区分、そして受託開発でHTTPのまま押し通す条件と別のプロトコルへ切り替える分岐点までを扱います。用語の言い換えではなく、仕様書に当たって設計判断を下せる状態を目標にします。
まとめ:プロトコル選定で先に決める3点と実装者が踏む確認の順序
プロトコルとは、通信する双方が事前に合意しておく規約です。どんなビット列を送るか(構文)、その並びが何を意味するか(意味)、どの順序でいつ送るか(タイミング)の3つを決めれば、実装が別々のベンダーでも通信が成立します。異なる言語の話者が会話できないのと同じで、規約が違えば機器は接続できません。
実務で決めるのは3点だけです。第1に階層のどこを触るのか。アプリケーションを書く立場なら、ほとんどの場合TCPやIPには触れず、HTTPの上で完結します。第2に既存の標準を使うか独自に作るか。結論を先に書くと、社内システムの受託開発で独自バイナリプロトコルを設計する理由はほぼありません。第3に通信の型がリクエスト応答型か、サーバ側からの継続的な配信型か。ここだけがHTTPで足りるかWebSocketやMQTTへ移るかの分岐になります。
確認の順序は、仕様書を読む前に実物を見る、です。curl -v で往復を1回見てから、該当するRFCの目次に当たる。逆順にすると、抽象的な階層図だけ覚えて実装で手が止まります。なお2026年9月時点の現行仕様は、TCPがRFC 9293(STD 7)、HTTPのセマンティクスがRFC 9110(STD 97)です。1981年のRFC 793を根拠に書かれた解説記事は、すでに廃止された文書を引いています。
プロトコルの定義:構文・意味・タイミングの3要素と階層の役割分担
プロトコルという語はIT以外でも使われますが、通信の文脈では定義がはっきりしています。「決まりごと」という訳語で止めず、何を決めているのかまで分解します。
構文・意味・タイミングの3要素と実際のHTTPヘッダに現れる形
構文はデータの形式です。HTTPなら、1行目に「メソッド 空白 パス 空白 バージョン」が来て、続けて「名前: 値」のヘッダが並び、空行の後に本文が来る、という並びが構文にあたります。GET / HTTP/1.1 の空白が1つ多くても、受け手は解釈できません。
意味は、その並びが何を要求しているかです。GET は取得、200 は成功、404 は対象が見つからないという合意があるから、実装の違うサーバとクライアントが会話できます。この意味の定義はHTTPのバージョンとは独立していて、RFC 9110側に集約されています。
タイミングは順序と時間の制約です。TCPなら接続確立のためにSYN、SYN+ACK、ACKの3往復を先に済ませます。HTTPなら、クライアントが要求を送り切るまでサーバは応答を返しません。3要素のうち実装で最も事故が起きるのはタイミングで、タイムアウト値の不一致や、応答を待たずに次を送る実装が典型的な障害要因になります。
階層に分ける理由:TCPを差し替えてもHTTPが動く設計の根拠
プロトコルは機能ごとに層を分けて設計されています。物理的な信号、機器間の転送、経路選択、送達の保証、アプリケーションの意味付けを一つの規約に詰め込むと、どこか一つを変えるたびに全体を作り直すことになるためです。
この分割が効いている実例がHTTP/3です。HTTPのメソッドやステータスコードの意味は据え置いたまま、下位のトランスポートをTCPからQUIC(UDP上)へ差し替えました。アプリケーション側のコードはほぼ変わりません。層の境界が守られているから、片側だけを置き換えられます。
層の数え方には流儀があり、7階層のOSI参照モデルと4階層のTCP/IPモデルが併用されています。どちらが正しいかという話ではなく、設計の教科書としてのOSIと、実装されている体系としてのTCP/IPという住み分けです。各層にどのプロトコルが対応するかはOSI参照モデルの7階層と各層プロトコルの対応に、実装から見た4階層の切り分けはTCP/IPの4階層モデルとOSIとの違いにまとめてあります。
標準化されたプロトコルと独自プロトコルの境目:相互接続性の損得
標準プロトコルの価値は、実装が既に揃っているという点です。HTTPを選べば、クライアントライブラリ、プロキシ、ロードバランサ、監視ツール、デバッグ用のcurlまで全部揃っています。独自プロトコルを設計した瞬間に、この周辺すべてを自前で用意する側に回ります。
標準化の実務的な意味は、仕様が文書として公開され、複数の実装が同じ文書を参照している状態です。IETFのRFCは誰でも無償で読めます。ベンダー独自仕様との差はここで、仕様書が非公開だと不具合の切り分け時に「どちらの実装が間違っているか」を判定できません。
境目の判断は単純です。相互接続する相手が社外にいる、あるいは将来いる可能性があるなら標準を選びます。閉じた組み込み機器同士で、帯域や電力に厳しい制約があり、既存標準ではフレーム長が収まらないと実測で示せる場合だけ、独自仕様に踏み込む価値があります。
通信を目で確認する手順:curlとsocketで見るHTTPの往復
階層図を眺めるより、1回実行したほうが早く理解できます。ここに載せる出力は2026年9月12日に手元のWindows 11環境(curl 8.21.0・Schannelビルド)で実際に取得したもので、作文ではありません。
curl -v で読み取るリクエスト行とヘッダとステータス行の並び
-v を付けると、送った行が >、受け取った行が <、curl自身の動作が * の印で区別して表示されます。
$ curl -v -o /dev/null --http1.1 https://example.com/
* ALPN: curl offers http/1.1
* ALPN: server accepted http/1.1
* using HTTP/1.x
> GET / HTTP/1.1
> Host: example.com
> User-Agent: curl/8.21.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/html
< Transfer-Encoding: chunked
< Connection: keep-alive
< Server: cloudflare
読む順番は、ALPNの2行で使うバージョンが決まり、> の4行が要求、空の > がヘッダ終端、< HTTP/1.1 200 OK が応答の1行目です。Transfer-Encoding: chunked が返っている以上、本文の長さは事前に分かりません。障害調査でまず確認するのはこのステータス行と、Content-Type と Connection の3つです。
TLS 1.3のネゴシエーション結果をPythonのsocketで確認する
ライブラリを剥がして、ソケットへ直接バイト列を書くと、HTTPが単なるテキストの取り決めだと分かります。次のコードはそのまま実行できます。
import socket, ssl
ctx = ssl.create_default_context()
with socket.create_connection(("example.com", 443), timeout=10) as raw:
with ctx.wrap_socket(raw, server_hostname="example.com") as s:
print(s.version(), s.cipher()[0])
s.sendall(b"GET / HTTP/1.1\r\nHost: example.com\r\n"
b"Connection: close\r\n\r\n")
print(s.recv(200).decode())
# 実行結果(2026年9月12日)
# TLSv1.3 TLS_AES_256_GCM_SHA384
# HTTP/1.1 200 OK
# Date: Fri, 11 Sep 2026 16:25:27 GMT
# Content-Type: text/html
要求の終わりが空行、つまり \r\n\r\n である点が構文の肝です。ここを \n だけにすると多くのサーバは応答を返しません。また server_hostname を渡さないと証明書の検証に失敗します。TLSの折衝結果が TLSv1.3 と表示されたのは、クライアントとサーバの双方がTLS 1.3に対応していたからで、片側が古ければ自動的に下位のバージョンへ落ちます。
ALPNでHTTPのバージョンが決まる仕組みと実測での確認点
上のcurlの出力で最初に出ていた ALPN: curl offers http/1.1 は、TLSハンドシェイクの中で「この後どのアプリケーションプロトコルを話すか」を申告する拡張です。HTTPのバージョン選択はHTTPの中ではなく、その下のTLSで先に決まります。
実測で見るべき点は2つです。クライアントが何を提示したか(offers の行)と、サーバが何を受諾したか(accepted の行)。この2行が食い違っていれば、想定と違うバージョンで通信しています。HTTP/2を有効にしたはずなのに速度が変わらない、という調査はここから始めます。
なお、ビルドによって使えるバージョンは変わります。手元のWindows版curl 8.21.0はSchannelを使うビルドで、--http2 を指定しても提示されたのは http/1.1 だけでした。ライブラリの対応状況は curl --version のFeatures行で確認できます。
ポート番号の3区分:IANAレジストリと自社サービスでの選び方
IPアドレスが機器を特定し、ポート番号が機器の中のどのサービスかを特定します。この番号の管理方法は仕様として決まっており、慣習ではありません。
System・User・Dynamicの3区分と各範囲の割り当て規則
ポート番号は16ビットで0〜65535です。RFC 6335(BCP 165・2011年8月)は、この範囲を3つに区切っています。
| 区分 | 範囲 | 割り当て | 別名 |
|---|---|---|---|
| System Ports | 0〜1023 | IANAが割り当て | Well Known Ports |
| User Ports | 1024〜49151 | IANAが割り当て | Registered Ports |
| Dynamic Ports | 49152〜65535 | 割り当てを行わない | Private / Ephemeral Ports |
どの番号がどのサービスに登録済みかはIANAのService Name and Transport Protocol Port Number Registryが現物です。80がHTTP、443がHTTPS、22がSSHという対応もここに記載があります。RFC 6335はDynamic Portsについて、常に空いている保証がないため「サービス識別子として使ってはならない」と明記しています。
自社サービスのポート選定の判断基準とエフェメラル枯渇の回避策
社内システムで新しくサービスを立てるときの番号選びは、User Ports(1024〜49151)から選び、Dynamic Portsの範囲を避ける、が基本です。49152以降はクライアント側が接続元ポートとして自動的に消費する領域で、そこに待ち受けを置くと起動タイミング次第で番号を取り合います。
1024未満のSystem Portsは、Linuxでは特権が必要です。アプリケーションを一般ユーザで動かしたうえで80番と443番を使いたい場合は、リバースプロキシを前段に置くか、Linuxのケーパビリティで権限を絞って付与します。コンテナで動かすなら、コンテナ内は8080番などで待ち受け、公開側のポートマッピングで443番に対応させる構成が扱いやすくなります。
接続元ポートの枯渇は、外部APIを高頻度で叩くバッチで実際に起きます。TCP接続を都度切ると、閉じた接続がしばらくTIME_WAIT状態で番号を保持するためです。対策はポート範囲を広げる設定変更ではなく、HTTPのkeep-aliveを有効にして接続を使い回すことが先です。
主要プロトコルの現行仕様:RFC番号・STD番号と旧版の置き換え
プロトコルの解説で最も陳腐化しやすいのが、参照しているRFC番号です。ここは2026年9月12日にRFC本文から実測した現行版を記載します。
TCPはRFC 9293・HTTPはRFC 9110へ統合された現行版
TCPの現行仕様はRFC 9293「Transmission Control Protocol (TCP)」(STD 7・2022年8月)です。1981年のRFC 793に加え、RFC 879・2873・6093・6429・6528・6691を廃止し、数十年分の変更を1つの文書へ集約しました。「TCPはRFC 793で定義されている」と書かれた解説は、廃止済みの文書を指しています。
HTTPはRFC 9110「HTTP Semantics」(STD 97・2022年6月)が現行です。RFC 2818と、7230番台のRFC 7231・7232・7233・7235などを廃止しました。設計上の要点は、メソッド・ステータスコード・ヘッダの意味をバージョン非依存のRFC 9110へ切り出し、HTTP/1.1・HTTP/2・HTTP/3それぞれの「送り方」を別のRFCへ分けたことです。ステータスコードの根拠を探すなら、まずRFC 9110を開きます。
TLS 1.3とQUICが置き換えた旧版と移行時に確認する点
TLSの現行版はRFC 8446「TLS Protocol Version 1.3」(2018年8月)で、TLS 1.2を定義していたRFC 5246を廃止しています。ハンドシェイクの往復が減り、旧来の暗号スイートが整理されました。先ほどのPythonの実行結果で TLSv1.3 と表示されたのは、この仕様に沿った折衝の結果です。
HTTP/3はRFC 9114(2022年6月)で標準化され、トランスポートにQUICを使います。TCPではなくUDPの上に構築されるため、経路上のファイアウォールがUDP 443番を落とす環境では接続できず、HTTP/2へ落ちます。移行時に確認するのはこの1点です。QUICが何を解決したかはQUICの仕組みとTCPとの違いで扱っています。
受託開発でのプロトコル選定:HTTPで足りる条件と切り替えの分岐点
ここからは仕様の紹介ではなく判断です。業務システムの開発現場で実際に選ぶときの基準を、条件付きで言い切ります。
HTTP 1.1のままで足りる条件:社内APIと低頻度バッチ
社内の業務システム間連携で、データの更新が人間の操作契機である限り、HTTP/1.1とJSONで足ります。画面で保存ボタンを押す、夜間バッチが1日1回走る、担当者がCSVを取り込む。これらは要求と応答が1対1で対応するリクエスト応答型で、HTTPの設計に合致しています。
ここで凝った選択をする必要はありません。gRPCやGraphQLは、マイクロサービスが数十あってスキーマ整合の維持コストが問題になっている、あるいはモバイル側の通信量削減が数値目標になっている、といった前提があって初めて割に合います。社内に数個のサービスしかない段階で導入すると、ツールチェーンの学習と運用に人手を取られて、得られる性能差は体感されません。
WebSocketやMQTTへ切り替える分岐点:更新頻度と接続数
切り替えの判断材料は2つ、更新の頻度と同時接続数です。サーバ側で発生した変化を秒単位で画面へ反映する必要があるなら、ポーリングの間隔を詰める前に双方向通信へ移ります。5秒間隔のポーリングは、1000クライアントで毎分12000リクエストになり、その大半が「変化なし」の応答です。
使い分けの判断軸は用途です。ブラウザと業務画面の間ならWebSocketのハンドシェイクと実装、センサーや現場端末のように接続数が多く回線が細い側ならMQTTのPub/SubとQoS設計が合います。MQTTは配信保証のレベルを選べるので、通信断が前提の環境で効きます。
逆に、更新が1時間に1回程度で、クライアントが社内の数十台に収まるなら、WebSocketは採用しません。常時接続を維持する分だけロードバランサや再接続処理の設計が増え、その手間に見合う効果が出ないためです。
独自バイナリプロトコルの設計を見送る場面:運用体制と要員の制約
独自プロトコルの設計を見送るべき場面は具体的に指定できます。運用と保守を自社の体制で続ける前提の業務システムであれば、見送ってください。理由は性能ではなく要員です。仕様書と実装の両方を書いた担当者が離任した瞬間、障害時にパケットを読める人間がいなくなります。
標準プロトコルなら、curlで再現でき、プロキシのログに残り、市販の監視ツールが解釈します。この差は運用年数が長いほど効いてきます。既存標準では要件を満たせないと判断する場合は、フレーム長や遅延の実測値を根拠として残したうえで進めてください。
プロトコルの選定とスキーマ設計を含む連携基盤の構築は、API開発・システム連携として対応しています。既存システムの通信方式が分からないまま刷新を検討している段階でも、現状の通信を実測して整理するところから相談を受け付けています。
よくある質問
プロトコルの理解でつまずきやすい点を、検索されている質問の形で整理します。
プロトコルとは簡単に言うと何ですか?
通信する双方が事前に合意している約束事です。何を送るか(構文)、それが何を意味するか(意味)、どの順序で送るか(タイミング)の3つを決めた規約を指します。日本語と英語しか話せない人同士で会話が成立しないのと同じで、対応する規約が違う機器同士は接続できません。IT以外では医療の実施計画書や外交儀礼も同じ語で呼ばれますが、通信の文脈では上記の意味に限定されます。
プロトコルと通信プロトコルは違うものですか?
通信の文脈では同じものを指します。「プロトコル」という語が医療や外交でも使われるため、IT分野であることを明示したいときに「通信プロトコル」と呼び分けているだけです。技術文書ではTCPやHTTPのような個別の名前で書かれることが多く、総称として使う場面は限られます。
プロトコルの種類は全部でいくつありますか?
確定した総数はありません。IANAのポート番号レジストリには数千のサービス名が登録されており、RFCとして公開された仕様も9000番台に達しています。実務で押さえる必要があるのは、HTTP、TCP、IP、DNS、TLS、SSHの6つ程度です。残りは必要になった時点で該当するRFCを読めば足ります。
TCPとHTTPはどちらが上の層になりますか?
HTTPが上、TCPが下です。HTTPの役割は「何を要求し何を返すか」を決めることで、TCPの役割は「そのデータを欠落なく順序どおり届ける」ことです。役割が分離しているため、HTTP/3ではTCPをQUICへ差し替えてもHTTPのメソッドやステータスコードはそのまま使えています。OSI参照モデルではHTTPが第7層、TCPが第4層にあたります。
プロトコルの現行仕様はどこで確認できますか?
IETFが発行するRFCが一次情報で、rfc-editor.orgから無償で読めます。注意点は、RFC番号が新しいほど現行とは限らないことです。文書の冒頭にある「Obsoletes」と「Status」を先に見てください。TCPはRFC 9293、HTTPのセマンティクスはRFC 9110が2026年9月時点の現行版で、いずれも2022年に旧文書を置き換えています。
関連記事
- OSI参照モデルとは?7階層の役割・各層プロトコル・TCP/IPとの違いを解説:層ごとにどのプロトコルが対応するかを一覧で確認できます。
- TCP/IPとは?4階層モデルとOSI参照モデルの違いを実装目線で解説:実装されている体系としての4階層の切り分けを扱っています。
- QUIC(通信プロトコル)とは?HTTP/3を支える仕組みとTCPとの違いを実装視点で解説:トランスポートを差し替えた事例として読めます。
- WebSocketとは?仕組み・ハンドシェイクからNode.js実装・運用の判断まで実装者向けに解説:双方向通信へ切り替える場合の実装手順です。
- MQTTとは?Pub/Subの仕組み・QoS・MQTT 5.0の実装からHTTPとの使い分けまで実装者向けに解説:接続数が多く回線が細い環境での選択肢になります。