TOP   Ruby

簡単なソケット通信

Google 検索

文字列の送信

サーバー側

require "socket"
 
# ポート番号20000番でopen
s0 = TCPServer.open(20000)
 
# クライアントからの接続を受け付ける
sock = s0.accept
 
# クライアントからのデータを最後まで受信する
# 受信したデータはコンソールに表示される
while buf = sock.gets
  puts buf
end
 
# クライアントとの接続ソケットを閉じる
sock.close
 
# 待ちうけソケットを閉じる
s0.close

クライアント側

require "socket"
 
# 127.0.0.1(localhost)の20000番へ接続
sock = TCPSocket.open("localhost", 20000)
 
# HELLOという文字列を送信
sock.write("hello")
 
# 送信が終わったらソケットを閉じる
sock.close

元ネタはここ。最初にサーバー側のプログラムを実行し、ついでクライアント側のを実行する。すると、サーバー側に「hello」が出る筈。
ここは参考にしないといけないな。

打ち込んだ文字を送信

サーバー側

require 'socket'
 
port = if ARGV[0] then ARGV[0] else 'echo' end
gate = TCPServer.open(port)
 
sock = gate.accept
gate.close
 
while msg = sock.gets
  sock.write(msg)
  print("you get:", msg)
end
sock.close

クライアント側

require 'socket'
 
host = if ARGV[0] then ARGV[0] else 'localhost' end
port = if ARGV[1] then ARGV[1] else 'echo' end
sock = TCPSocket.open(host, port)
 
while msg = STDIN.gets
  print("you writed:", msg)
  #socketに書き込む
  sock.write(msg)
  #サーバから返ってきたメッセージを表示する。
  print("return message:", sock.gets)
end
sock.close

クライアント側で何か文字を打ち込むと、そのままサーバー側に表示される。
元ネタはここ

Socket.openというのは、新しいソケットを作成する。
Socket#bindで、作成したソケットをシステムに知らせる。自分自身のIPアドレスやポート番号をbindメソッドに渡す。
bindメソッドで、特定のポートへのソケットの割り当てを行う。
その次は、Socket#listenである。
接続を受け入れられる状態にする。

Socket#acceptで、接続を確立させる。
本の例えがわかりやすかったんだけど、listenしているポート番号は総合受付の窓口で、そこで接続要求が受理(accept)されると、個別の窓口(新しいソケットのポート番号)に案内されて、以後はその窓口でやり取りを行うという仕組みになっている。

そんなにむずかしいことではないな。open して、write したり gets したりしているだけだ。最後は close も普通のファイル操作と同じ。
しかし、ポートが accept されたら直ぐ閉じてしまっていいのかな。これできちんと動いているから、いいのだろうが。

今度は二台の PC でやってみる。サーバーを Linux機にして上を実行したら、何か echo に関してエラーが出たので、ポート番号を 20000 にしてやってみる。クライアント側も同じポート番号にして、さらに IPアドレスを引数にして実行。クライアント機に打ち込んだ文字列が、ちゃんとサーバー機の画面上に表示されましたよ。うーん、嬉しいなあ。こうやってネット通信するというわけだ。

ファイル転送

TCPServer(検索)というのがいまひとつよくわからないな。取りあえずリファレンス・マニュアル


ソケット通信を使った、テキストファイルの簡単な転送プログラムです。セキュリテイなどは何も考えていません。

サーバー側

require 'socket'
 
fname = "transfered.txt"
s = TCPServer.open(20000)
data = s.accept; s.close
f = File.open(fname, "w")
while a = data.gets
  puts a
  f.write(a)
end
f.close
data.close

クライアント側

require 'socket'
 
ipa = "192.***.**.**"
s = TCPSocket.open(ipa, 20000)
fname = ARGV[0]
f = File.open(fname, "r")
while a = f.gets
  puts a
  s.write(a)
end
f.close
s.close

まずサーバー側のプログラムを動かし、次にクライアント側のを、転送したいファイル名を引数にして実行します。クライアント側は、変数 ipa にサーバー側の IPアドレスを入れておかねばなりません。クライアント側のテキストファイルが、サーバー側の "transfered.txt" ファイルへと転送されます。

自分は最初クライアント側に Windows 機、サーバー側に Linux(Lubuntu)機を使って上手くいったのですが、逆の構成では成功しませんでした。何かがおかしいのですが、よくわかりません。Windows ファイアーウォールは切ってやったのですが。

inserted by FC2 system