ソケット、プロセスおよびストリームの入出力
ストリームのタイプによって詳細が異なる部分もありますが、これらを操作する基本のプロセスはすべて同じシーケンスに従います。開く、読み取りおよび/または書き込み、閉じる。標準入力、標準出力および標準エラーのストリームは常に開いているとみなされるため、本シーケンスの主な例外は、これらのストリームは開閉を必要としないことです。
以下に、スクリプト内でソケット、プロセスおよびストリームの操作に使用するコマンド、関数、およびグローバルプロパティを示します。
- open socket / open process
- close socket
- read
- write
- openSockets() / openProcesses()
- the defaultStringEncoding
ソケットの出入力コマンド(open socket、close socket、read from socket、およびwrite … to socket)を使用すると、別のプロセスから提供されるソケットへの接続を開き、その接続を通してデータの読み書きを行うことが可能になります。ソケットは2つのプロセス間で開いている通信チャネルにすぎないため、ソケット上の特定の場所をシークすることはできません。
同様に、プロセスの出入力コマンド(open process、close process、read from process、およびwrite … to process)により、外部プロセスを起動し、そのプロセスの標準入力への書き込みと標準出力からの読み取りによって、そのプロセスとの通信が可能になります。
また、readおよびwriteコマンドは、標準入力からの読み取りと、標準出力または標準エラーストリームへの書き込みにも使用できます(read from input、write … to output、write … to error)。
openSockets()関数は、現時点で開いているすべてのソケットのリストを返します。
the defaultStringEncodingグローバルプロパティは、ファイルまたはソケットからテキストの読み書きを行う際に使用する符号化フォーマットを制御します。
Open Socketコマンド
挙動:readまたはwriteコマンドを利用してソケットからの読み取り取りまたはソケットへの書き込みを行う前に、open socketコマンドを利用してソケットを開ける必要があります。ソケットの操作が終了したら、close socketコマンドを利用してソケットを閉じる必要があります。
Open socketは、別のプロセス(プログラム)へのTCPソケット接続を確立します。その他のプロセスは、同一のコンピュータ、またはネットワーク上のその他のコンピュータで実行します。使用するコンピュータは既に起動しており、SenseTalkが接続できるソケットを前もって登録しておく必要があります。接続の確立後は、データは双方が理解できる何らかの手段で、両方向に転送されます。
構文:
socketIdentifierはhost:portの形式とする必要があり、ここで、hostはマシンの名前またはIPアドレス、portは接続先のソケットのマシン上のポート番号を指します。
socketIdentifierはオプションで、末尾にナンバー記号「#」(またはバーティカルバー「|」)とその後に任意の数または識別子の文字列を付けることができます。これは、同じホストとポートへの2つ以上の接続を確立し、各接続を一意に特定するのに複数の識別子を作成できるようにするという目的に適合します。すなわち、read、writeおよびcloseコマンドと一緒に適切なsocketIdentifierを使用することで、正しい接続を特定できます。
readTimeoutグローバルプロパティで指定された時間内にソケット接続を確立できない場合は、例外が投げられます。現在開いているすべてのソケットのリストを入手するには、openSockets()関数を使用します。
例:
open socket remoteListener
例:
open socket "192.168.1.4:22"
例:
open socket "localhost:5900#2"
Open Processコマンド
挙動:外部プロセスを起動し、スクリプトがそのプロセスとやり取りするための接続を開きます。外部プロセスを実行し、その完了時にこのプロセスから出力を受け取ることで十分な場合は、shell()関数を利用すると、これらの操作を非常に簡単に実行できます。一方、open processメカニズムは極めて高い柔軟性を提供するため、スクリプトが別のプロセスと複雑なやり取りを行ったり、スクリプトを遮断することなくかなり長い演算を開始し、スクリプトの後半でその演算の結果を回収することが可能になります。
Open processは、シェルの可能性がある(そして最も一般的にはシェルである)別のプロセス(プログラム)を起動し、これを介してその他のプログラムが継続して実行されます。別のプロセスの起動後は、接続が確立され、テキストが両方向に転送されます。すなわち、スクリプトがそのプロセスの標準入力への書き込み、および標準出力からの読み取りを行います。
プロセスを起動できない場合は、result()関数を例外に設定します(the throwExceptionResultsグローバルプロパティがtrueに設定されている場合は、例外が投げられます)。openProcesses()関数を利用すると、現在開いているすべてのプロセスのリストを入手できます。
構文:
processIdentifierは、processPath#identifierの形式をとる必要があります。ここで、processPathは実行するプロセスのフルパスを表します。processPathを省略すると、(the shellCommandグローバルプロパティで指定した)シェルプロセスが起動します。#identifierの部分はオプションであり、processIdentifierを一意にする方法として機能するにすぎないため、スクリプトは同じprocessPathを使用する複数のプロセスを一度に開いてやり取りすることができます。
optionsを使用する場合は、以下のプロパティのいずれかを含むプロパティリストである必要があります。
パラメータ |
プロセスの起動時にパラメータとしてこのプロセスに渡される値のリスト |
フォルダまたはディレクトリ |
プロセスを実行する現在のディレクトリ |
環境 |
環境変数とその値を指定するプロパティリスト |
例:
open process preferredShell & "#myshell"
例:
open process "/bin/sh" with options myOptions
例:
open process "/usr/local/bin/mysql#2"
Close Socket、Close Process、Close Allコマンド
挙動:単一のソケット、プロセス、または開いているすべてのファイル、ソケットもしくはプロセスを閉じます。close all socketsコマンドは、ソケットを開けたスクリプトやハンドラに関係なく、現在開いているすべてのソケットを閉じます。この挙動は、その他のスクリプトでソケットを開き、継続して使用している場合に問題となる可能性があります。現在開いているすべてのソケットのリストを入手するには、openSockets()関数を使用します。同様のことが、close all processesコマンドについても当てはまります。
close socketコマンドは、open socketコマンドによって開けられたソケットを閉じます。socketIdentifierは、ソケットを開ける際に使用した識別子と同じである必要があります。
close processコマンドは、open processコマンドによって開けられたプロセスを閉じます。processIdentifierは、プロセスを開ける際に使用した識別子と同じである必要があります。
close all socketsおよびclose all processesコマンドは、現在開いているすべてのソケットまたはプロセスを閉じるのに使用できます。スクリプトの実行が中止されるごとに、SenseTalkが開いているすべてのソケットとプロセスを自動的に閉じますが、操作の終了時にスクリプトがこれらを閉じるようにすることが推奨されます。
構文:
close socket socketIdentifier
close process processIdentifier
close all sockets
close all processes
例:
close all processes--開いているすべてのプロセスを閉じます
例:
close socket "localhost:5900"
例:
close process "#9"
Read from Socket、Read from Process、Read from Inputコマンド
挙動:開いているソケットもしくはプロセス、または標準入力ストリームからデータ(テキストまたは数字)を読み取ります。
read from ...コマンドを利用すると、ソケット、プロセス、または標準入力からデータを読み取ることができます。データの読み込み先となるのは、変数itか、格納先コンテナ(into節を使って指定した場合)です。読み取るデータがそれ以上なくなったら、格納先コンテナが空になります。要求よりも少ないデータが読み取られた場合は、result関数には常にその理由を与える値が含まれます(time outなど)。
readコマンドは、特定の数の文字や単語、アイテム、行の読み取り、または指定された区切り文字が見つかるまで読み取りを行ったり、複数の異なるタイプの数値のいずれかのリストを読み取ることができます。読み取りは、現在の位置から開始されます。readコマンドの構文には柔軟性があり、さまざまなオプションを都合の良い順番で指定することができます。
構文:
オプション:
from process processIdentifier
from [input | stdin]
into container
until [terminator | eof | end]
{for} quantity {dataType}
in timeLimit
読み取り先のソースを指定するには、3つのfromオプションのいずれかを使用する必要があります。その他のオプションは任意で使用できますが、タイプごとに1つのオプションを指定できます。forオプションもuntilオプションも指定しない場合は、単一の文字が読み取られます。
例:
read from input until return -- ユーザーが入力したテキストを読み取ります
例:
read from process mysql until end -- 入手可能なテキストを読み取ります
例:
read into numList from socket inStream for 3 unsigned integers
例:
read 6 unsigned 8-bit integers from socket rfb into unitSales
例:
read 10 chars from socket "192.168.1.4:22" in 15 seconds
テキストチャンクタイプの代わりに数値のデータタイプを指定した場合、読み取りによってitまたはコンテナに格納される値は、読み取られたデータ値のリストになります。使用できる数値のデータタイプは次のとおりです。
データタイプ |
値 |
int1または8-bit integer |
符号付き8ビット(1バイト)整数 |
uint1またはunsigned 8-bit integer |
符号なし8ビット(1バイト)整数 |
int2または16-bit integerまたはshort integer |
符号付き16ビット(2バイト)整数 |
uint2またはunsigned 16-bit integer |
符号なし16ビット(2バイト)整数 |
int4または32-bit integerまたはinteger |
符号付き32ビット(4バイト)整数 |
uint4またはunsigned 32-bit integer |
符号なし32ビット(4バイト)整数 |
int8または64-bit integer |
符号付き64ビット(8バイト)整数 |
uint8またはunsigned 64-bit integer |
符号なし64ビット(8バイト)整数 |
real4または32-bit realまたはfloat |
32ビット(単精度)浮動小数点数 |
real8または64-bit realまたはdouble |
64ビット(倍精度)浮動小数点数 |
技術トピック
標準入力ストリームは常に開いているため、これを開く必要はありません(好みに応じて、入力ではなくstdinと呼ぶことができます)。
ソケットから読み取りを行う場合は、socketIdentifier式は、open socketコマンドを用いてソケットを事前に開いた際に使用した正確な識別子を生成する必要があります。
プロセスから読み取りを行う場合は、processIdentifier式は、open processコマンドを用いてプロセスを事前に開いた際に使用した正確な識別子を生成する必要があります。読み取られた値は、プロセスからの標準出力に対応します。
into コンテナを指定すると、読み取られたデータがその指定のコンテナに格納されます。intoオプションを指定しない場合は、データは特別なit変数に読み込まれます。
until終端子を指定すると、開始位置から指定文字または文字列の次の出現箇所までの全文字が読み取られます。これは、(終端文字としてreturnを使用して)ソースから一度に1行ずつ読み取る場合や、 ちょうどその他の(tabなどの)区切り文字まで読み取る場合に役に立ちます。終端子は2文字以上でも構いません。また、終端子も読み取られた値の一部として返されます。until eofまたはuntil endを指定すると、ファイルの最後まで、またはソケットもしくはストリームからの入力の最後まで読み取りを行います。標準入力ストリームは、Control-D文字を受け取った後であることを示します。ソケットまたはプロセスにおけるuntil eofまたはuntil endオプションは、入力が利用可能になるまで、またはreadTimeoutもしくはin timeLimitの期間が経過するまで(以下を参照)待機します。これにより、入力が予想される際の読み取りが大幅に簡素化されます。
for 数量データタイプを使用した場合、数量で指定した分の文字数またはその他のデータ要素数がファイルから読み取られます。データタイプがテキストチャンクタイプ(characters、words、itemsまたはlines)の場合、その要求分の数量が得られるまでテキストが読み取られます。最後の区切り文字(存在する場合)は、読み取られるテキストには含まれません。データタイプを与えない場合は、charactersと仮定されます(この場合、forという語を入れる必要があります)。
in timeLimitオプションは、要求されたデータが利用可能になるまでreadコマンドが待機する最長の時間を与えます。時間を指定しない場合は、代わりにthe readTimeoutグローバルプロパティの値が使用されます。timeLimitまたはreadTimeoutが指定する時間内に要求データが読み取られない場合は、読み取られたデータに関わらずすべてのデータが返され、the result関数がtime outを示すように設定されます。
Write to Sockets、Write to Process、Write to Output、Write to Errorコマンド
挙動:ソケットもしくはプロセス、または標準出力ストリームもしくは標準エラーストリームにデータを書き込みます。データには、有効な任意のSenseTalk式を入れることができます。データタイプを指定しない場合、データ式の値は、文字列として扱われ、指定のソケットまたはストリームに書き出されます。
socketIdentifier式は、open socketコマンドを用いて事前に開けたソケットの識別子を生成する必要があります。
processIdentifier式は、open processコマンドを用いて事前に開けたプロセスの識別子を生成する必要があります。書き込まれたデータは、プロセスの標準入力に送られます。
as データタイプを指定した場合、書き込み前にデータがバイナリ形式に変換されます。この場合は、データを数値リストとすることができ、これらはすべて同じデータタイプに変換されます。有効なデータタイプの一覧については、readコマンドを参照してください。
構文:
write data {as dataType} to socket socketIdentifier
write data {as dataType} to process processIdentifier
write data {as dataType} to [output | stdout | error | stderr
例:
write "ls -l" & return to process "#4"
例:
write "Please enter your account id: " to output
例:
write (2,3,5,9) as 8-bit integers to socket msock
OpenSockets関数
挙動:open socketコマンドの結果として、現在開いているすべてのソケットのリストを返します。
構文:
openSockets()
the openSockets
例:
repeat with each item of the openSockets
if it begins with "192.168.1.12:" then close socket it
end repeat
OpenProcesses関数
挙動:open processコマンドの結果として、現在開いていてやり取りに利用できるすべてのプロセスのリストを返します。
構文:
openProcesses()
the openProcesses
例:
repeat with each item of the openProcesses
if it begins with "/usr/bin/ssh" then
write "logout" & return to process it
end if
end repeat