Techracho

iPhoneのCookie

このエントリーをはてなブックマーク Share
2010.01.09    ネットワーク, 馬場   タグ: , —    baba   

最近は地味にiPhone SDKで試行錯誤中です。

基本的な内容ばかりになると思いますが、気づいた点を書いていこうと思います。

今日はCookieについて。

まず、一番単純なHTTPリクエストは、以下のようなコードで実行できます。
(実際は同期通信だと色々まずいので、非同期通信を使うことが多いと思います)

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.bpsinc.jp"]];
NSURLResponse *response;
NSError *error;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

//結果を表示
NSString *str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", str);

この際、サーバ側でセッションを開始するなどしてCookieの発行を指示した場合、レスポンスヘッダにSet-Cookieが入ります。
これを受け取ると、NSURLConnectionが自動的にCookieを保存してくれます。
そのため、次回同じURLにリクエストした場合、保存されているCookieが送信されます。

このCookieを取得するには、以下のような手順を踏みます。

NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
NSArray *cookies = [storage cookies]; //cookiesForURLで絞り込みもOK
for (int i = 0; i < [cookies count]; i++) {
    NSHTTPCookie *cookie = [cookies objectAtIndex:i];
    [storage deleteCookie:cookie]; //削除する
}

これで、セッションの強制的な解除などが実現できます。

NSHTTPCookieStorageに保存されているCookieは、Safariなどと共有されているらしいです。
このあたりはもう少し実験してみようと思います。

UAC有効だと、HttpListenerExceptionが発生する

このエントリーをはてなブックマーク Share
2009.12.26    C#, ネットワーク, 馬場      baba   

C#でHTTPサーバを作るのはすごく簡単、

HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://*:8000/"); //ポート番号は好みで。80でもOK
listener.Start();

while (true)
{
	HttpListenerResponse response = listener.GetContext().Response;
	response.OutputStream.Write(data, 0, (int)data.Length); //ここで何かdataを出力する
	response.Close();
}

のようなコードだけで出来てしまいます。

しかし、これだとWindows Vista / 7 のUAC有効環境で、HttpListenerExceptionが発生します。
Windowsファイアウォールを無効にしても結果は変わりません。

UAC有効の状態では、通常権限のプログラムは、localhost以外からの接続を受け付けられないようです。

そもそもテストやミニプログラム以外でHttpListenerを使うか疑問が大きいので、手抜きで安直な解決方法を探ってみます。

localhostに限定
ローカルでテストする分には、
listener.Prefixes.Add(”http://localhost:8000″);
のようにすればとりあえず動きます。

管理者権限にする
localhost以外からも接続させたいなら、管理者権限で動かしてしまうのが簡単です。
Visual Studioを起動する際に管理者権限にしておけば、デバッグで起動するプログラムも管理者権限になるので、例外は発生しなくなります。

クロスドメインDojo

このエントリーをはてなブックマーク Share
2009.08.22    dojo toolkit, javascript, ネットワーク, 馬場      baba   

Dojoは、デフォルトでは読み込み元HTMLと同じサーバに置くことを前提に作られています。
具体的には、dojo.require()が、XMLHttpRequestを使ってデータを取得します。

このため、同じドメインにライブラリを設置できない場合(共有サーバで権限が無い時など)、クロスドメインの制限でdojo.require()が失敗してしまいます。
dojo.parserなどの内部でrequireを使っているため、ライブラリの読み込み時点でエラーが多発してしまいます。

この場合は、クロスドメインビルドをしたdojoライブラリ(XDomain Dojo)を使用します。

方法1: AOLを使用
お手軽に使うには、AOLのCDNを活用します。
http://dev.aol.com/dojo に書いてあるように、以下の形式でdojoライブラリを読み込むだけでOKです。

<script type=”text/javascript” src=”http://o.aolcdn.com/dojo/1.3/dojo/dojo.xd.js”></script>

この場合、dojo.requireは、デフォルトで用意されているdojo, dijit, dojoxのみ使用可能で、自前のコンポーネントは使用できません。

方法2: クロスドメインDojoのビルド
方法1はお手軽ですが、AOLのサーバが重いとか、自前で設置したいこともあると思います。
その場合、Dojoをソースからビルドします。

  1. ソースを入手
    まず、Dojoのダウンロードサイトから、ソースを取得します。dojo-release-1.3.0-src.zip のように、srcが付いているものがソースです。
    ダウンロードサイト: http://download.dojotoolkit.org/
  2. ビルド
    そして、以下のページの手順に従い、ビルドします。
    ビルドの手順: http://www.dojotoolkit.org/book/dojo-book-0-9/part-4-meta-dojo/package-system-and-custom-builds

    具体的には、以下のコマンドでビルドできます。(Linuxの場合)
    xdDojoPathに、Dojoライブラリを設置するディレクトリ名を記述します。テスト環境と本番環境ではURLが違うと思うので、その場合は2回ビルドする必要があります。
    パックするライブラリを変更したい場合は、profileを変更します。

    $ cd util/buildscripts
    $ build.sh profile=standard loader=xdomain xdDojoPath=http://www.bpsinc.jp/dojoxd action=release

    以上のコマンドを入力すると、ビルドが始まり、しばらくするとreleaseフォルダにXDomainビルドされたDojoが生成されます。

  3. 設置
    xdDojoPathに設定したフォルダに、dojoを設置します。
    上記の例では、DocumentRootのdojoxdフォルダに、dojo/dijit/dojox が入っている状態になります。
  4. 読み込み
    あとは、

    <script type=”text/javascript” src=”http://www.bpsinc.jp/dojoxd/dojo/dojo.xd.js”></script>

    のように読み込めばOKです。

Windows 7 RCでインターネットに接続できない場合

このエントリーをはてなブックマーク Share
2009.05.14    Windows, ネットワーク, 馬場   タグ: , , —    baba   

メインマシンをWindows 7にしました。
Vistaの良さを引き継ぎつつ、動作が軽快になって、かなり良いWindow 7ですが、まだRCなのでたまに問題が起こります。

今日は、再起動したらネットワーク接続がおかしくなりました。
IPアドレスは取得できているし、ルーターまでは接続できるのに、外につながりません。

これは、デフォルトゲートウエイの設定が間違っていたのが原因でした。
本来の値(192.168.100.1)のほかに、謎の0.0.0.0が追加されていました。
DHCPのあたりにバグがあるのか、ルーターとの相性問題が発生したのかもしれません。

以下、内側ネットワークを192.168.100.0/24, デフォルトゲートウエイを192.168.100.1と仮定します。

【問題が発生していた状態】
> ipconfig
IPv4アドレス: 192.168.100.205
サブネット マスク: 255.255.255.0
デフォルト ゲートウエイ: 0.0.0.0
            192.168.100.1

ネットワークアダプタのプロパティで設定しようとしたのですが、DHCPとうまく両立して手動設定する方法が見つからなかったので、コマンドプロンプトを使用しました。

> route delete 0.0.0.0
> route add 0.0.0.0 MASK 0.0.0.0 192.168.100.1

【正常な状態】
> ipconfig
IPv4アドレス: 192.168.100.205
サブネット マスク: 255.255.255.0
デフォルト ゲートウエイ: 192.168.100.1

これで、正常に外部に接続できるようになります。
注意点としては、通常のコマンドプロンプトで実行すると権限エラーが出るので、コマンドプロンプトを「管理者として実行」するか、runasコマンドを使うことです。

XAMPPのApacheが起動しない

このエントリーをはてなブックマーク Share
2009.03.10    Windows, ネットワーク, 馬場   タグ: , —    baba   

XAMPPでApacheが起動しなくてちょっと困りました。
XAMPP Control PanelでApacheの「起動」を押しても、瞬時に終了してしまいます。

コマンドプロンプトで
C:\xampp\apache\bin>apache.exe
を実行したら、httpd.conf (C:\xampp\apache\conf\httpd.conf) が間違ってるというエラーが出てきました。(ServerRootとDocumentRootを間違えた)

いや、書き間違える僕が悪いんですが、終了する前にエラーを出して欲しかった。
コマンドプロンプトから実行したときだけ、ちゃんとエラーを見せてくれます。

EthnaでXML-RPCの引数を連想配列にする

このエントリーをはてなブックマーク Share
2009.03.04    PHP, Web, ネットワーク, 馬場   タグ: , —    baba   

Ethnaは標準でXML-RPCに対応しているので、
# ethna add-action-xmlrpc hoge
とやるだけで app/action-xmlrpc にActionのテンプレートが作れますし、クライアントからHogeメソッドをコールすると、自動的にHogeアクションが実行されます。
(エントリポイントはindex.phpではなくxmlrpc.phpになります)

しかし、デフォルトでは引数がActionFormのform定義と順番に1対1で対応するため、引数が多くなると使いづらくなります。

ここは、PHPらしく引数名をキーにした連想配列にしたいところ。
(プロジェクト名)_Controller に以下のメソッドを定義(オーバーライド)することで、XMLRPCの第一引数を連想配列として扱い、対応する名前のformに値がセットされるようになります。

function trigger_XMLRPC($method, $param)
{
    // アクション定義の取得
    $action_obj =& $this->_getAction($method);
    if (is_null($action_obj)) {
        return Ethna::raiseError("undefined xmlrpc method [%s]", E_APP_UNDEFINED_ACTION, $method);
    }

    // オブジェクト生成
    $backend =& $this->getBackend();

    $form_name = $this->getActionFormName($method);
    $this->action_form =& new $form_name($this);
    $def = $this->action_form->getDef();
    
    /***** ここから変更 *****/
    if (isset($param[0]) && is_array($param[0]))
    {
        foreach ($param[0] as $key => $value)
        {
            if (isset($def[$key]))
            {
                $this->action_form->set($key, $value);
            }
        }
    }
    /***** ここまで変更 *****/

    // バックエンド処理実行
    $backend->setActionForm($this->action_form);

    $session =& $this->getSession();
    $session->restore();
    $r = $backend->perform($method);

    return $r;
}

これで、クライアント側では引数の順番を気にせずに済みます。

ノートン先生

このエントリーをはてなブックマーク Share
    Windows, セキュリティ, ネットワーク, 馬場   タグ: —    baba   

家族のPCにNorton Internet Security 2009体験版を入れてみたところ、Shurikenでのメール送受信が出来なくなりました。
POP3S/SMTPSは使えるのですが、POP/SMTPが使えない状態です。インストール直後は平気だったのに、ウィルススキャンをしたらだめになったとか。

110番と25番許可にしたり、ファイアウォールの一番上に全部許可のルール入れたり、アプリケーション制御で信頼するアプリに登録したり、ファイアウォールオフにしたり、ノートン先生丸ごとオフにしたり、色々やっても解決せず、

再起動したら直りました。謎。

やっぱり僕はKasperskyが好きです。高いけど。

System.Windows.Forms.Timer が動かない

このエントリーをはてなブックマーク Share
2009.02.10    C#, Windows, ネットワーク, 馬場   タグ: , —    baba   

C#でスレッドを使うときの注意です。

System.Windows.Forms.Timer はお手軽でよく使いますが、このTimerはUIスレッドでのみ動くためなのか、別スレッドから呼ぶと動かないみたいです。

System.Threading.Thread や System.Threading.Timer、TcpListener::BeginReceive() などで作ったスレッド内で System.Windows.Forms.Timer を作ってStart()メソッドを呼んでも、Tickはいくら待っても呼ばれません。


//テストコード
Thread thread = new Thread(new ThreadStart(delegate {
    System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer { Interval = 1000 };
    timer.Tick += new EventHandler(delegate { MessageBox.Show("HOGE");});
    timer.Start();
}));
thread.Start();

上記のテストコードで、メッセージボックスは永久に出ません。
System.Windows.Forms.Timer を System.Threading.Timer に変えれば動くので、これは System.Windows.Forms.Timer の制約のようです。

ネットワークでパケット受信をトリガに処理を始めるときなど、うっかりミスしないように気をつけましょう。

TcpListenerを使ったTCPサーバ

このエントリーをはてなブックマーク Share
2009.01.26    C#, Web, Windows, ネットワーク, 馬場   タグ: , —    baba   

C#のTcpListenerを使って、サーバを作っていています。

System.Net.Sockets.Socket.Available プロパティは、信用してはいけません。
下のコードは、クライアントから接続があってもたまにしか受信できません。

using (Socket client = listener.AcceptSocket())
{
  //ここにThread.Sleep(1000)とかを入れるとうまく動くことも多い・・・

  while (client.Available) //ここでいきなりfalseが返ってくる
  {
    byte[] buf = new byte[256];
    client.Receive(buf);
    Console.WriteLine(Encoding.ASCII.GetString(buf));
  }
}

この場合、次のようにするのが正しいです。

using (Socket client = listener.AcceptSocket())
{
  byte[] buf = new byte[256];
  int bytes;
  while ((bytes = client.Receive(buf)) > 0)
  {
    Console.WriteLine(Encoding.ASCII.GetString(buf));
  }
}

それから、TcpListenerのコンストラクタは第一引数にローカルIPアドレス、第二引数にポート番号を渡しますが、サーバに置いては
TcpListener listener = new TcpListener(IPAddress.Any, 45678);
のように IPAddress.Any を渡すのが正しいです。「ローカルIPアドレス」といっても、サーバマシンのアドレスでは無く、クライアントのアドレスを渡します。わかりにくい。。

ネットワークエラーの解決

このエントリーをはてなブックマーク Share
2009.01.02    Linux, ネットワーク, 仮想化, 馬場   タグ: , , —    baba   

仮想サーバのNICに負荷をかけるとホストマシンごと落ちる件について、現状改善したように見えるので、解決記録を書いておきます。

まず蟹が原因と思い、ヨドバシカメラにNICを買いに行きました。新春セールでポイント5%アップで幸せ気分です。
本当はIntelが欲しかったけど売ってなかったので、玄人指向のGBE-PCIe(Marvell 88E8053)とGbE-PCI2(VIA VT6122)を買ってきました。PCIeが良いのでMarvellの方を使うつもりで、VIAは予備用に買いました。

早速Marvellに差し替えたところ、負荷をかけてもホストOSは落ちなくなりました。やっぱり蟹が原因だったみたいです。
(ちなみに、NICのMACアドレスが変わった場合、Ubuntuの場合 /etc/udev/rules.d/70-persistent-net.rules を編集すれば eth0 に割り当てるなど出来ます)
しかし、ホストOSは落ちないものの仮想サーバの通信は負荷をかけるとやっぱり切れてしまいます。
調べてみると、eth0: out-of-sync dirty pointer というエラーを出していました。また、ifconfigをみるとエラーがたくさんあります。

そこで、使っていたBUFFALO製のスイッチングHUBを外して、仮想サーバ用のMarvellとRTX1000を直接つないでみたら、負荷をかけてもエラーが出なくなりました。
スイッチングHUBをcorega製に変えてみても、エラーは出ませんでした。

つまり、RealtekのNICとBAFFALOのHUBが両方悪かったみたいです。
値段だけで選ぶと痛い目に遭いますね。

« 新しい投稿古い投稿 »

COPYRIGHT [C] 2009 BEYOND PERSPECTIVE SOLUTIONS LTD. ALL RIGHTS RESERVED.