- up: 📂プログラミング
- refs.
ソケットプログラミングとは
ソケット(Socket)
実行中のプログラム間でデータの送受信を行うための標準的なプログラミングインターフェース (API) の一つ.
TCP/IP アプリケーションを作成するための抽象化されたインターフェース
通信端点, 通信の出入り口になるようなドアの概念.
EndPoints
端末.一意に定まる通信先.
Socket は IP Address と PortNo.をつかって, 通信先のソケットを特定する. ネットワークに接続されたパソコンや PDA, 携帯電話などのネットワーク端末の総称. エンドボイントに Socket がバインドされる.
Loopbacks
IP アドレスは必ずしもリモートホストと関連付けられている必要はない. とくに開発環境では, ローカルな IP アドレスが役に立つ.
自端末に対して通信することを LoopBack という. LoopBack で指定するアドレスを Loopback Address という.
- ハードウェアと関係ない, 論理的なインタフェース.
- Linux では, localhost と言われている. IP は 127.0.0.1
Ports
ポートフォワーディング
ローカルコンピュータの特定のポートに送られてきたデータを別に用意した通信経路を用いてリモートコンピュータの特定ポートに送信すること.
ref. ポートフォワーディングとは 【 port forwarding 】
たとえば, Windows ファイルサーバに,SSH 経由で (CIFS, port 445/tcp で) アクセスする (した).
Stream
データの入力または出力の機能を提供する抽象データ型. メッセージの境界という境界がない. TCP/IP プロトコルはストリームベースの設計.
ref. ストリーム (プログラミング) - Wikipedia
Blocking/Non-Blocking
ブロッキング
送受信の完了を待ってから他の処理を開始する通信方法.
require 'socket'
server = TCPServer.new (2803)
while client = server.accept
input = client.readline
client.write "You said: #{input}"
client.close
endノン・ブロッキング
データの送受信を行う際に, 送受信の完了を待たず他の処理を開始する通信方法.
ref. ノンブロッキング通信とは 〔 ノンブロッキングモード 〕
require 'socket'
server = TCPServer.new (2803)
loop do
Thread.new (server.accept){ |client|
input = client.readline
client.write "You said: #{input}"
client.close
}
endExample Ruby
Server Lifecycle
- create ソケットの生成
- bind
- ソケットを利用する Port にバインド.
- User でバインドする Port は 1025-48999
- ソケットが通信を許可する IP を指定.
- 0.0.0.0: すべて許可
- 127.0.0.1: 自端末のみ許可
- xxx.xxx.xxx.xxx: ある端末のみ許可
- ソケットを利用する Port にバインド.
- listen 通信先ソケットからの通信をまつ
- accept 通信先ソケットからの通信を受け取り, 通信路 をそのつど生成 (connection)
- close 通信元ソケットの消滅.
# coding: utf-8
require 'socket'
# 1. create
server = Socket.new (:INET, :STREAM)
# 2. bind
addr = Socket.pack_sockaddr_in (4481, "0.0.0.0")
server.bind (addr)
# 3. listen
server.listen (5)
# 4. accept
loop do
connection, _ = server.accept
## send message from client.
# ehco "Hello" | nc localhost 4481
p connection
# it should be closed each connection
connection.close
end
# 5. close
server.closeTCPServer
Ruby では, 以下のような糖衣構文がある.
ref. class TCPServer
server = TCPServer.new (4481)
# =>
# server = Socket.new (:INET, :STREAM)
# addr = Socket.pack_sockaddr_in (4481, "0.0.0.0")
# server.bind (addr)
# server.listen (5)Client LifeCycle
- create ソケットの生成
(2. bind )
- connect サーバと接続
- close ソケットの破棄
require 'socket'
# 1. create
socket = Socket.new (:INET, :STREAM)
# 3. connect
remote_addr = Socket.pack_sockaddr_in (80, 'google.com')
socket.connect (remote_addr)
# 4. close
socket.closeTCPSocket
Ruby では, 以下のような糖衣構文がある.
ref. class TCPSocket
socket = TCPSocket.new ('google.com', 80)
# =>
# socket = Socket.new (:INET, :STREAM)
# remote_addr = Socket.pack_sockaddr_in (80, 'google.com')
# socket.connect (remote_addr)Simple Read
以下の例では, 永遠にサーバは Read を待ち続けて, その先が進まない.
require 'socket'
Socket.tcp_server_loop (4481) do |connection|
puts connection.read
connection.close
endSocket は指定されたデータ長のデータが到着するまで待ち続ける. デッドロックを回避するためには,
- Client 側で データの最後で EOF を送信する.(EOF event)
- Server 側で一度に読み込むデータ長を小さくする. (partial read)
Client のソケットが close メソッドを実行すると, その延長で EOF が通知される.
🔖通信タイムアウト
Socket Timeout/Connection Timeout/Connection Request Timeout
JavaのApache HttpClentの使用だがいろんな言語実装で登場するのでまとめておく. 設定可能な3つの属性の意味はそれぞれ以下の通り.
- socket timeout: ソケット通信のスタートから終了まで.
- connection timeout: クライアントからサーバへの接続確立(3way-shake)まで
- connection-request-timeout: 接続確立後からレスポンスが返るまで.
ref. JavaのHttpClientにおける3つのTimeoutの違いに関して - Qiita
エラーが発生したときの障害解析で大事なのは, 自分が悪いのかサーバが悪いのかという問題.
Connection Timeoutはサーバへの通信が届いてないのでサーバは悪くない. Socket Timeoutはサーバからの通信か切れたのでサーバが悪いかも.
connection timeoutは3の倍数
TCPの仕様で3秒ごとに状況確認をするようで, 3の倍数で設定するのがよいとのこと.
【Python】requestsを使うときは必ずtimeoutを設定するべき | Cosnomi Blog
Broken pipe
よくssh接続とかで見かけるやつ. プログラムを動かしていて通信エラーでもでる.
packet_write_wait: Connection to
port 22: Broken pipe Broken pipeと出力される原因はクライアントからサーバ(ssh接続先)に対して一定時間無操作ためタイムアウトにより切断されたと思われます.
これはクライアント側が被疑箇所の可能性. サーバからの応答完了を待たずに接続終了. しかし応答を待っているのが期待時間外あればサーバが被疑箇所の可能性もある. いずれにしろリトライによって救済を試みることがよい.