iT邦幫忙

DAY 6
6

回應鐵人賽的文章變鐵人系列 第 6

[Reply] 用Ruby實作最簡單的UDP的Server及Client

由於UDP是非連接導向(stateless)的協定,
較容易了解最基本的socket的server與client如何溝通。
目標:
Server 端接收Client送過來的字串,
然後在server端顯示出時間、從何IP、送出什麼字串;
並且回應所指定的訊息給該client。

udp.client.rb

require 'socket'
require 'timeout'

log = UDPSocket.new
msg = ARGV[0]
log.connect('localhost', 4443)
log.print ARGV[0]
log.print "Done!"
timeout(10) do
  time = log.gets
  puts time
end

上述的第6行,明顯地是定義連到何IP及port,
利用print的方法,送出指令,
由gets來獲得server回應的東西。
timeout是可具有緩衝的時間來接受server端的回應。

udp.server.rb

require 'socket'
socket = UDPSocket.new
socket.bind('',4443)
loop do
  msg, sender = socket.recvfrom(100)
  host = sender[3]
  puts "#{Time.now}: #{host} '#{msg}'"
  socket.send(Time.new.to_s  + " #{sender.inspect} -- ##{sender[1]}" + "\n", 0, sender[3], sender[1])
end

上述的第三行指定用什麼IP及port為server端的接口,
並利用迴圈不斷偵測是否有資料丟進來,
而第5行由recvfrom的方法,
獲得丟來的資料及 不明的陣列資料,
第七行在server端馬上秀出記錄,
也可改寫成輸出到某log檔裡;
第八行就是最重要地怎麼送給client,
其實socket.send最基本的寫法是:
server.send("某回應" + "\n", 0, sender[3], sender[1])
這樣的格式,搞不清楚那 sender 的陣列內容是什麼?
而用程式碼的第八行的 sender.inspect 的方式,
列出該內容。

執行及回應:

$ ruby udp.client.rb Helo
2010-10-05 20:48:42 +0800 ["AF_INET", 38376, "127.0.0.1", "127.0.0.1"] -- #38376

$ ruby udp.server.rb
2010-10-05 20:48:42 +0800: 127.0.0.1 'Helo'
2010-10-05 20:48:42 +0800: 127.0.0.1 'Done!'

從這樣的具體實作的例子,
這個圖可以大概了解那麼多種的socket之間的關係為何:

再仔細要弄清楚 ruby 的 socket 文件 時,
才不至造成混淆;
再以這樣的基礎,
慢慢地把socket中不同的項目或方法來套用試試。

這是先從實例實作,
再去看理論、規格是什麼,
由下往上的路徑來探索。
是與先理論後實作的程序相反,
就看每個人適合怎樣子的學習。

系列文章


上一篇
[Reply] 用Ruby來體驗 socket 的實作
下一篇
[Reply] 不會有安全的資料或傳遞,除非用加密的方式
系列文
回應鐵人賽的文章變鐵人30

2 則留言

0
SunAllen
iT邦研究生 1 級 ‧ 2010-10-05 23:50:40

疑惑完全看不懂Orz

0
逮丸逮丸
iT邦大師 1 級 ‧ 2010-10-06 08:39:05

有需要的時候,就會逼自己…至少可以work,
可work,就有機會慢慢改成自己的需要,
當可以改成自己的需要時,
就會比較了解點自己是在做什麼。
所以,需要是看得懂之母吧?!

至於為什麼要做socket server的練習?
就當成是要做一個不同於http的port及protocol的server,
其實像ftp、pop3、imap、bbs、dns…等,甚至http,
算是已有完整規格的socket server及client的規範來依循的實作產品。
p2p也應是本身兼有socket server及socket client的雙重角色,
適用於不靠web界面時的 開始自行造輪子 的工作。

我要留言

立即登入留言