開発者目線でWeb3におけるP2Pまとめ

by AIGRAM

ブロックチェーンにはP2P(Peer to Peer/ピア・トゥー・ピア)という技術が使われています。この技術により、全てのブロックチェーンノードで取引履歴を共有しており、信頼性担保・対データ改竄性にとても重要な項目となっています。

ブロックチェーンにはP2P(Peer to Peer/ピア・トゥー・ピア)という技術が使われています。この技術により、全てのブロックチェーンノードで取引履歴を共有しており、信頼性担保・対データ改竄性にとても重要な項目となっています。

目次

P2Pの特徴

メリット

  • サーバーを介さずコンピュータ同士を直接接続して通信する
  • 分散管理:P2Pでやりとりされるデータは、個々のコンピュータに存在する
  • ゼロダウンタイム:P2Pでは最低限、通信を行うコンピュータだけが動作していれば、通信はいつでも可能
  • 低コスト:P2Pは最低限、送信元と送信先の機器を構築しネットワークで接続すれば通信できる

デメリット

  • 通信相手の信頼性の確保が難しい
  • 共有ファイルを通じウイルスに感染しやすく情報漏えいにまで発展する
  • 管理者がいないので、著作権侵害を犯しやすい

P2Pの種類

ピュアP2P

クライアント同士のみで接続してデータのやりとりを行う

ハイブリッドP2P

通信自体はクライアント同士で行うが、データの保存先はサーバー。

スーパーノード型P2P

優れた処理能力かつ通信回線が安定しているノードが、接続しているノードの情報を管理する

P2Pの使用例

LINE

  • 写真や動画の共有の仕組みにP2P技術が使われている
  • 大規模なサーバーが不要でコストがかからない

ビットコイン

  • ブロックチェーンのブロック(分散台帳)にデータを書き込む際にP2P技術が使われている
  • 1つのノードが消滅しても記録されたデータが残る

Skype

  • ユーザー同士の通話やファイル共有などに、P2P技術が利用されている(過去)

ソケット通信

複数のアプリ間で通信を行う仕組み自体をP2Pと言います。 ここではより詳細な通信手法について考えていきます。

ソケット通信

「ソケット通信」は2つのアプリ間で双方向に行う通信方法です。 類語として「HTTP通信」という言葉もありますが、こちらは一方向(クライアント側のアプリからサーバー側のアプリにアクションを促す)にデータを送信・受信します。 上位概念であるソケット通信を利用して、HTTP通信を実現しているとのことです。

TCP通信

Pythonでの実装例として、ポート8000で待機しているサーバーにクライアントからメッセージを送り、そのメッセージ内容を出力するプログラムを作成します。

server.py

  • サーバー側で通信を待機するプログラムです
  • 一度通信を行ったらプログラムは停止します
  • 通信があると、print文でその内容が出力されます
  • 今回の例では、「こんにちはサーバーさん」と出力されます
  • 「socket.AF_INET」は「IPv4」を表します
  • 「socket.SOCK_STREAM」は「TCP通信」を表します
server.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# server.py
import socket

# ポート8000で通信待機
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('localhost', 8000))
sock.listen(1)

# クライアントとのソケット通信開始
conn, addr = sock.accept()

# メッセージの送受信
data = conn.recv(1024)

# クライアントとのソケット通信終了
conn.close()

client.py

  • 待機中のサーバーに通信を行うクライアント側のプログラムです
  • 送信するメッセージはエンコードしなければいけません
client.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# client.py
import socket

# サーバーとのソケット通信開始
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.connect(('localhost', 8000))

# メッセージの送受信
message = 'こんにちはサーバーさん'
conn.sendall(message.encode('utf-8'))

# サーバーとのソケット通信終了
conn.close()

以下ステップで通信が行われていることを確認できます。

  1. server.pyを起動
  2. client.pyを実行
  3. server.pyを実行したコンソールで「こんにちはサーバーさん」を確認

UDP通信

TCPとUDPの違い

先ほどのプログラムではTCPという方式で通信を行いました。 これとは別にUDPという方式もありますので、まとめておきます。

・接続してから通信を行うか(TCP)、接続せずに通信を行うか(UDP) ・UDPは信頼性よりも効率性を重視 ・UDPは高速に処理できる  ・余分なヘッダがない(8バイト)  ・接続確認がない(TCPでは接続確認後に通信が行われる) ・UDPは音声や動画などのリアルタイム配信に使用される ・UDPはDNSやDHCPなどの速度が優先される通信に使用される ・UDPは一度に複数の相手にデータを送信する「マルチキャスト通信」や「ブロードキャスト通信」が行える

UDPで通信するサンプルコードを作成します

server.py

  • 「socket.SOCK_DGRAM」は「UDP通信」を表します
  • 待機関係の記述(accept、listen)が不要なのでシンプルな印象です
コード
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import socket

# ポート8000で通信待機
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('localhost', 8000))

# メッセージの送受信
message, cli_addr = sock.recvfrom(1024)
print(message.decode())

# クライアントとのソケット通信終了
sock.close()

client.py

  • 接続(connect)が不要なのでシンプルな印象です
コード
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import socket

# サーバーとのソケット通信開始
conn = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# メッセージの送受信
message = 'こんにちはサーバーさん'
conn.sendto(message.encode('utf-8'), ('localhost', 8000))

# サーバーとのソケット通信終了
conn.close()
  1. server.pyを起動
  2. client.pyを実行
  3. server.pyを実行したコンソールで「こんにちはサーバーさん」を確認