基本的なソケット通信
import socket
サーバー = socket.socket() # TCPプロトコルをデフォルトで使用
サーバー.bind(('IPアドレス', ポート番号)) # IPとポートのバインディング
サーバー.listen(5) # 接続待ちキュー
クライアント, アドレス = サーバー.accept() # 接続受付、3ウェイハンドシェイク完了状態
データ = クライアント.recv(1024) # データ受信
クライアント.send(送信データ) # データ送信
クライアント側 = socket.socket()
クライアント側.connect(('IPアドレス', ポート番号))
通信のロジックとエラーハンドリング
-
通信ループ: 受信と送信をwhileループで繰り返す。
-
接続ループ: 監視コードをwhileループで継続する。
-
コードの堅牢性:
- 例外キャッチ:try-except構造を使用。
- ポート競合の確認。
- システム問題:クライアントとサーバーそれぞれで入力や受信データが空か確認。
TCPの特性と解決方法
-
TCPパッケージング: 小規模なデータをまとめて送信(ストリームプロトコル)。
-
対策:
- 固定長ヘッダーを使用し、structモジュールでデータのパッケージ化を行う。
- クライアント側:
1. 固定長ヘッダーパッケージを作成し送信。
2. 実際のデータを送信。
- サーバー側:
1. 固定長ヘッダーを受信。
2. 実際のデータを解析し受信。
大ファイル転送の方法
-
一貫性の検証: hashlibモジュールでファイル内容をハッシュ化し、一致確認。
-
データ保存: 行ごとにforループで送信・保存。
UDP通信の実装
# サーバー側
import socket
udp_server = socket.socket(type=socket.SOCK_DGRAM)
udp_server.bind(('127.0.0.1', 9000))
メッセージ, アドレス = udp_server.recvfrom(1024)
udp_server.sendto(送信データ, アドレス)
# クライアント側
udp_client = socket.socket(type=socket.SOCK_DGRAM)
ip_port = ('127.0.0.1', 9000)
udp_client.sendto(データ, ip_port)
応答, アドレス = udp_client.recvfrom(1024)
print(応答.decode('utf-8'), アドレス)
並行処理と並列処理
-
並行処理: 単一CPU上で複数タスクを時間分割で実行。
-
並列処理: 複数CPUで同時に実行。
マルチプロセスの理論と実践
from multiprocessing import Process
import time
def タスク(name):
print(f'{name}が動作中')
time.sleep(3)
print(f'{name}が終了')
if __name__ == '__main__':
p = Process(target=タスク, args=('プロセス1',))
p.start()
class カスタムプロセス(Process):
def __init__(self, name):
super().__init__()
self.name = name
def run(self):
print(f'{self.name}が動作中')
time.sleep(3)
print(f'{self.name}が終了')
if __name__ == '__main__':
p = カスタムプロセス('プロセス2')
p.start()
プロセス間通信の制限と対策
-
データ分離: 各プロセスは独立したメモリ空間を持つため、直接のデータ共有は不可。
プロセス管理のオブジェクトメソッド
from multiprocessing import Process, current_process
import os
def タスク(name):
print(f'{name}が動作中')
time.sleep(3)
print(f'{name}が終了')
if __name__ == '__main__':
p = Process(target=タスク, args=('プロセス1',))
p.start()
p.join()
p.terminate()
print(p.is_alive())
print(current_process().pid)
print(os.getpid())
print(os.getppid())