Hatena::Groupmoz-addon

Ci.nsIZIGOROu

2007-10-17うーむ

JScriptで始めるネットワークプログラミング - Echoサーバー編

| 21:38 |  JScriptで始めるネットワークプログラミング - Echoサーバー編 - Ci.nsIZIGOROu を含むブックマーク はてなブックマーク -  JScriptで始めるネットワークプログラミング - Echoサーバー編 - Ci.nsIZIGOROu

これも続編は期待しないこと。w

ソース

var winsock = WScript.CreateObject("MSWinsock.Winsock", "winsock_");
var sctl = WScript.CreateObject("ScriptControl");

sctl.Language = "VBScript";
sctl.AddObject("WScript", WScript);
sctl.AddCode('Function GetData(wsock): Dim brcv: wsock.GetData brcv, vbstring: GetData = brcv: End Function');

winsock.Close();
winsock.LocalPort = 7777;
winsock.Listen();
  
function winsock_ConnectionRequest(reqID) {
  WScript.Echo("reqID: " + reqID);
  winsock.Close();
  winsock.Accept(reqID);
}
  
function winsock_DataArrival(bytesTotal) {
  WScript.Echo("Bytes: " + bytesTotal);
  var rcv = sctl.Run("GetData", winsock); 
  WScript.Echo("Data: " + rcv);

  winsock.SendData(rcv);
}

function winsock_Error(eNum, eDesc, eScope, eSource, eHelpFile, eHelpContext, eCancel) {
  WScript.Echo("desc: " + eDesc);
  winsock.Close();
  WScript.Quit();
}

while(true)
  WScript.Sleep(1000);

使い方

適当な名前で保存する。echoserver.jsで保存したとして、

$ cscript //NoLogo echoserver.js

で起動します。

他の端末から、

$ telnet localhost 7777

みたいに接続して適当に文字を打つとEchoが返ってきます。

解説

MSWinsock.WinsockはWinSockコントロールのProgIDです。Listenする場合はバインドするポートをLocalPortプロパティに入れてListen()をコールするだけです。簡単ですね。

後は接続要求が来たときにClose()で一旦初期化した上で、Accept(reqID)すればクライアントからの接続を受け付けます。この時のハンドラはprefix_ConnectRequest(reqID)です。*1

一番厄介だったのは、Dataが送られてきた際のWinSockのGetData()の呼び出しです。

元のIDLだと、

void GetData(
                [in, out] VARIANT* data, 
                [in, optional] VARIANT type, 
                [in, optional] VARIANT maxLen);

となっているので、参照渡しでdataを渡さなければならないのですが、これは残念ながらJScriptでは出来ないです。

この部分の解決はScriptControlを使ったVBScriptで何とかしてます。GetDataのtype部分にvbstringと言う定数を渡しているのがミソです。

この辺りXPCOMだったら引数名をプロパティに定義してあるオブジェクトを渡してやると上手い事、そのプロパティに値を代入してくれるんですけど、COMの場合はそんな枠組みは多分無さそう。


まぁ、色々試した結果だけどWSHでもCOMを叩けば色々出来るってのが分かったので面白かった。

*1:prefixはWScript.CreateObjectで指定した値。あるいはWScript.ConnectObject()で後から指定する事も出来る。

MugMug2007/10/21 00:23すみません、返信が遅れました。(最近ブログ更新サボっていて、前向きなコメントを頂くとは想定外でした…)
私の場合は、ECMAScript(JavaScript,JScript)のコードをライブラリ化してまとめてインクルードでき、かつ多段(プロトタイプ)継承とプライベートメンバ・メソッドな「クラス(ユーザー定義オブジェクト)」を作る。
また、ライブラリ化の方針としては、ECMAScript準拠の部分と環境依存部分を別"クラス"や別"パッケージ"または"サブクラス"に分けて、なるだけ様々な環境で動作できるようにしています。
WSHでもそれらは動くのですが、せっかくスクリプト言語なのでCUIの対話形式での実行環境を作ってみましたのです。
(似てるのかな…?)スミマセン今はとりあえず返信させて頂こうかと思いましたので、後々内容を読ませていただきますね。

ZIGOROuZIGOROu2007/10/21 05:17おお、コメントありがとうございます。

> ライブラリ化してまとめてインクルードでき

この辺りは僕はScriptControlでやろうと思っています。
ただScriptControlはまだ挙動がいまいちわかってない部分があるんですよねぇ。

> かつ多段(プロトタイプ)継承

これはちょっとこの言葉だけだと想像出来ないかも。。。

僕も対話形式のConsoleは作ってるんですけど、まだライブラリ化の方針まで固まってません。ScriptXは使おうと思ってますけど。

MugMug2007/10/22 21:40いろいろとActiveXとか使ってますねー。いったいどこで仕様とか調べるのでしょう…??
後々参考にさせていただくかも知れません。

>> かつ多段(プロトタイプ)継承
JAVAなんかはクラスベースの継承だけれど、ECMAScriptはプロトタイプベースの継承ですよね。ただ、関数を使ったユーザー定義オブジェクトの場合、継承のシステムはユーザーが用意しなければならないはずです。
私の場合は、クラスライクな継承を何段も(サブクラスのサブクラスのサブクラスの…)できるようにしたのでこのように書かせていただきました。ただし、やはり多重継承はできませんでした。その代わり、"クラス"に1つ(static)なプロパティも継承させることにしました。

こっそり、こんなことやってます。

ZIGOROuZIGOROu2007/10/23 22:00> いろいろとActiveXとか使ってますねー。いったいどこで仕様とか調べるのでしょう…??

どこだろ、、、OleViewとかですかね?w
http://del.icio.us/zigorou でその手のブクマが流れてると思います。

で、継承云々の話ですけど、そもそも継承を積極的に使うべきかって辺りでJavaScriptのprototypeベースはそこまで要らない気がするんですよねぇ。

基本は普通にprototypeにベースとなる"オブジェクト"を突っ込んであげるだけで事足りると僕は考えていて、それ以上に拡張したいならmixinすればいいと考えてます。

型チェックってよりメソッド名で実装してるかしてないかみたいな。

takuya_1sttakuya_1st2007/10/29 12:00私のコードで使えるものがあればぜひ

ZIGOROuZIGOROu2007/10/31 00:58> id:takuya_1stさん
そう仰って頂けるのは恐縮です><