HTTP通信とソケット通信の違いってなんだ?となっていたらWebSocketと理解が混同していたとわかったのでまとめ。
ソケットとは
プロセスのもつ出入り口。プロセス間で通信を行う場合や、プロセスからインターネットに繋ぐ場合の口となる。
ソケット通信
インターネットを利用してWebサーバと通信する時には、TCPで通信を行うためのソケットを用意し、そこに相手のIPとポート番号を指定する。そしてコネクションを確立するとデータのやりとりを自由にできる仕組み。
プロセスがソケットを介して外と通信する時にはカーネルが介在する。
ネットワークからパケットが到達すると、カーネルはネットワークインターフェースで受信しIPヘッダとTCPヘッダを見て各プロセス(アプリケーション)が用意しているソケットに適切に選別してソケットバッファにデータを格納する。
ソケット通信の準備〜開始〜終了まで
サーバ側 クライアント側
1) socket() ソケット作成 1) socker()
2) IPアドレス+ポート番号の設定 2) IPアドレス+ポート番号の設定
3) bind() ソケットに名前つける
4) listen() 待機
5) accept() <-3) connect() 接続要求 # 3way handshakeが行われるのはここ
6) 通信 read()/write() 4) 通信 read()/write()
7) close() 閉じる 5) close() 閉じる
クライアント側ではbindが明示的にされないと、connectする際に任意のポート番号がカーネルから割り振られるので明示的にbindしなくても通信できる。
(なお、サーバ側も明示的にbindしなくてもいいが結局どのポートから送っているのかわからないのは困るのであとから調べる事になる。)
TCP/IP
送る側
- 送信するデータをパケット単位に分けて送る。
- それにより複数の通信で一つの回線を使える。
ルータ
-
ルータはパケットの宛先を見て正しく送ることだけが責任範囲。
-
目的地に届いたかは保証しない。
→ これを保証させるのがTCP(Transmission Control Protocol)の仕組み。
送る方と受け取る方でどのパケットがロストしたかを把握し、ルータは知らなくていいという仕組み。 -
経路に障害があったら別の経路を見つけるのもルーティングの仕事。
受け取る側
- 足りてないパケットを再要求する。
TCP/IP通信開始
TCPで通信を開始する(セッションを構築する)には始めに3way handshakesと呼ばれる通信が行われる。。
- SYNパケット(synchronize) : 通信していいですか?
- SYN + ACK(acknowledgement) : いいですよ、こちらも通信しますね
- ACK : いいですよ
TCPのセッションは、5タプル(プロトコル番号6、送信元IP、送信元ポート番号、宛先IP、宛先ポート番号)で区別している。
余談 (UDP)
UDPは後から開発されたもの。プロトコル番号が17番なのもその理由。
TCP/IPという呼び方ももとはTCPが当たり前だったから(パケットロスしない仕組みは必須)。ところが、音声等は多少ロスしてもリアルタイムである事の方が大事じゃない?となり、TCPからIPを切り離すことになった。
HTTP通信とソケット通信の違いってなんだ?
→ ソケット通信はTCP/IPレベルの通信である。アプリケーション層の通信であるHTTP通信も当然ソケットを使用している。ここで言うソケット通信と、HTTP通信と比較されるWebSocket
は別物。
WebSocket
通信規格の1つ。
クライアント側からしか通信を開始できないというHTTP通信の問題に対応することができる(双方向通信)。
HTTPでの様々な解決方法
従来のHTTPを用いて双方向通信を実現する様々な手段が検討されてきた。
-
ポーリング
… 定期的にサーバ側に変更がないかを問い合わせる。→サーバ負荷やばい。サーバ側の変更反映のラグ。 -
Comet : ポーリングを少し改善
… サーバ側に変化があるまでぎりぎりまでレスポンスを保留 →やはり上記の問題あり。 -
Server Sent Events(SSE)
… チャンクデータとして分割して結果を返しているように見せる。コネクションをcloseしていないのでサーバ側からその後もデータを送りつづけらる。 → コネクションの占有時間が長く他のアプリケーションに影響。
新しい解決方法:WebSocket
WebSocketはこの問題に対応した新しい通信。
- 双方から任意のタイミングで通信を開始できる。
- ヘッダめっちゃ少ない(HTTP通信はヘッダ情報がでかい)。
WebSocket通信の開始
WebSocket opening ハンドシェイク
HTTPのUpgradeヘッダを用いてWebSocketの通信をリクエストし、サーバ側から101を返すことでプロトコルを変える。
このハンドシェイクを通してWebSocketによる通信が開始される。
なお、WebSocketは新しい通信規格であるため未対応の通信機器も多い。もちろんルータなどを対応させる訳にはいかない。
→ TLS/SSLで暗号化してあたかもhttps://
のようにしまえばルータなどの通信経路上からはわからないため破棄されにくいということでwss://
も利用される。