これからネットワーク関係の業務が始まる.

ネットワークの知識をつけるためにソケットプログラミングの本を読み始めた.

2021.11.30追記: リンク先がなくなりました. 販売終了か?

本の内容

Ruby をつかって, ソケットプログラミングの内容が解説されている.この本のよさは, まさに,

安い, はやい, うまい

である.

  • Amazon Kindle で購入できるから, 1000 円で即時に手に入る.
  • はじめのほうが丁寧にかかれているので, Ruby さえしっていれば, 短時間でソケットプログラミングのエッセンスを速習できる.
  • たった 100p ちょいの厚さだけれども, 要点がまとまっていてる.

初めの 1/3 は基本のサーバ・クライアントプログラミング.C 言語にも通じる内容を Ruby で解説している. わたしの業務ははじめは Ruby でプロトタイピングをして, そのあと Java で書く予定.なので, 言語に縛られない知識が欲しい. そういう意味で, 基礎を学ぶことは有意義.

自分は以前, C で 軽くネットワークをかじったので, Ruby での簡潔さに驚いた. いろいろメソッドが解説されるのだけれども, 最後に Ruby の糖衣構文がでてきて, ほーら Ruby だとこんなに簡単にかけるんだよーといわれる.

中盤は, Non-Blocking I/O やマルチソケットプログラミングなど, やや専門的なな内容を扱っている. 自分の仕事では利用するところとしないところ我ありそうなので, つまみ食いしつつ読んでいる (今ここ)

驚いたのが終盤の章だ. ネットワーキングのアーキテクチャパターンが解説されている. 結構マニアック.そして, coursera でここを学んだ, そしてまだ学んでいる自分としては, この参考資料はうれしい.

ソケットプログラミングの基礎メモ

以下, かんたんなメモ.

Socket

  • 実行中のプログラム間でデータの送受信を行うための標準的なプログラミングインターフェース (API) の一つ.
  • TCP/IP アプリケーションを作成するための抽象化されたインターフェース
  • ソケット (BSD) - Wikipedia

EndPoints

端末.一意に定まる通信先.

Socket は IP Address と PortNo.をつかって, 通信先のソケットを特定する. ネットワークに接続されたパソコンや PDA, 携帯電話などのネットワーク端末の総称.

エンドボイントに Socket がバインドされる.

Loopbacks

IP アドレスは必ずしもリモートホストと関連付けられている必要はない. 得に開発環境では, ローカルな IP アドレスが役に立つ.

自端末に対して通信することを LoopBack という. LoopBack で指定するアドレスを Loopback Address という.

  • ハードウェアと関係ない, 論理的なインタフェース.
  • Linux では, localhost と言われている. IP は 127.0.0.1

ループバックとは 〔 ローカルループバック 〕

Server Lifecycle

  1. create ソケットの生成

  2. bind

    • ソケットを利用する Port にバインド.
      • User でバインドする Port は 1025-48999
    • ソケットが通信を許可する IP を指定.
    • 0.0.0.0: すべて許可
    • 127.0.0.1: 自端末のみ許可
    • xxx.xxx.xxx.xxx: ある端末のみ許可
  3. listen 通信先ソケットからの通信をまつ

  4. accept 通信先ソケットからの通信を受け取り, 通信路 をそのつど生成 (connection)

  5. 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.close

TCPServer

Ruby では, 以下のような糖衣構文がある.

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

  1. create ソケットの生成

(2. bind )

  1. connect サーバと接続
  2. 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.close

TCPSocket

Ruby では, 以下のような糖衣構文がある.

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
end

Socket は指定されたデータ長のデータが到着するまで待ち続ける. デッドロックを回避するためには,

  • Client 側で データの最後で EOF を送信する.(EOF event)
  • Server 側で一度に読み込むデータ長を小さくする. (partial read)

Client のソケットが close メソッドを実行すると, その延長で EOF が通知される.

最後に

来週からつかう知識だとだとおもうと, 知識を吸収しようという集中力が違う.

それは, 不安だからでもある. 知識を求めるのは, 自分の無力感を感じたくないから. 仕事が遅れて辛いおもいをしたくないから.

はたして, これからやってけるかな…