Squeak でソケット通信
sumim さんのSqueak Smalltalk 向けの分散処理関連で遊ぶ - Smalltalkのtは小文字ですに刺激を受けて、以前pythonでsocket入門: 思い立ったが吉日生活 さんと同じ事を Squeak でやってみる、と言うのを 試した時のメモを引っ張りだしてみました。
ソケット通信開始
Python が IDLE なので、Squeak は Workspace で お手軽ファイト!です。 (初めて Workspace 変数のありがたみが解りましたよ)
"Server-side (Smalltalk)" sock _ Socket newTCP. "TCPソケットの作成" sock listenOn: 7777. "ポート7777 で接続待ち" sock waitForConnectionFor: Socket standardDeadline. "クライアントのアクセス待ち"
#waitForConnectionFor: で アクセス待ちになります。 引数に取るのはタイムアウト時間で、通常は Socket >> #standerdDeadline を使えばOKです。
ちなみにPython版はコレ。ほとんど1対1 の対応になってます(当たり前だけど)。 accept のあたりが違いますが、そこは後述します。
#Server-side (Python) import socket sock = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) # TCPソケットの作成 sock.bind(('',7777)) # ポート7777で、 sock.listen(1) # 接続待ち conn, addr = sock.accept() # クライアントのアクセス待ち
さて、今度はクライアントサイド。
"Client-side(Smalltalk)" sock _ Socket newTCP. "TCPソケットの作成" sock connectToHostNamed: 'localhost' port: 7777. "localhost:7777 に接続"
これも Python版とほぼ一対一になります。
#Client-side (Python) import socket sock = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) # TCPソケットの作成 sock.connect(('localhost',7777)) # localhost:7777 に接続
Client→Server通信
"Client-side(Smalltalk)" sock sendData: 'Hello! I am Squeak Socket client'.
#Client-side (Python) sock.send( 'Hello! I am Python Socket client' )
戻り値は送信バイト数になります。 今度はこれを、サーバー側で取得してみましょう。
"Server-side(Smalltalk)" Transcript cr; show: sock receiveData Server-side (Python) print conn.recv(1024)
Transcript に以下のように出力されます。
Hello! I am Squeak Socket client
Server→Client通信
今度はサーバーから通信してみます。
"Server-side(Smalltalk)" sock sendData: 'Welcome to Squeak socket Server!'
例によって、戻り値として送信バイト数を返します。 コレをクライアント側から取ると
"Crient-side(Smalltalk)"
Transcript cr; show: sock receiveData
Socket通信の終了
サーバーもクライアントも、
sock close
するだけです。
Squeak 版の欠点(?)
2007.08.24 訂正。
以下は嘘です。単に使い方が悪いだけでした...orz
見ての通り、 Squeak版では サーバ側でクライアントコネクション待ちしたときに、 Python 版とは異なり connection オブジェクトを返していません。 (Python 版だと connection オブジェクトを介して send() や recv() を行っている)
つまり、このやり方だと複数クライアントと会話できない、一度に一人しかアクセスできません。
実は Squeak の Socket にもちゃんと #accept メソッドがあります。 新しいコネクションの Socket オブジェクトを返してくれるハズなのです。
接続待ちでは、#waitForAcceptFor: なんていう いかにもお誂え向けのメソッドがいて、 これは結局中で #waitForConnectionFor: をしたあと、#accept で新しいソケット(子ソケット)を返してくれる ・・・という風な動きをします。
しかし、コレを使って
sock _ Socket newTCP.
sock listenOn: 7878.
con _ sock waitForAcceptFor: Socket standardDeadline.
のようなコードを作っても、 コネクション確立した後に呼び出される #accept から辿りたどった Socket >> #primiAcceptFrom:receiveBufferSize:sendBufSize:semaIndex: 内の
全然追っかけてないし、私のソケットの理解は甘いので ただ「動かない」って言ってみただけなのだけれど、 Squeakでネットワーク(サーバサイド) さんも accept を使わないで「欠点は一度に一人じか接続できない」て解説してるのをみると、 なんかあるのかな?と思わなくもないです。