[Top Page][Edit][Discussion][Edit History][All Pages][Recent Changes][->Japanese]

httpクライアントサンプル

Pcbnet2の最新バージョンPublic Beta 2を使って簡単ネットワークプログラミング。


流れ tcpopen→tcpiscon→tcpput→(tcpsend)→tcpgetl→tcprecv
流れ解説
ソケットオープン→接続を確認→リクエストヘッダ送信→(データ送信=POST時など)→レスポンスヘッダ受信→レスポンスボディ受信
自分で工夫しなければいけないのは、リクエストヘッダの生成や、レスポンスヘッダの処理からレスポンスボディの受信など。

  • Pcbnet(Pcbnet2)を使う利点
    • ブロッキングされない。(すぐに制御をHSPに返してくれるので動作が固まることがない)
    • 細かいところは気にせずシンプルなコードが書ける
    • HSPSOCKより機能が多い
    • 通信バッファ関係がHSPSOCKよりも効率的になっている。
    • 最低以下の5つ(tcpsendを除く)の命令だけでhttpクライアントが作れる。(telnet/sntp/mailクライアントも応用で作成可)

書式

  • tcpopen
    サーバーのポートに接続を試みる。tcpisconと併用する。
    tcpopen p1,"p2",p3
    p1 : ソケットIDを格納する変数
    p2 : 接続先サーバー名
    p3 : 接続先ポート番号
  • tcpiscon
    p1で指定されたソケットが接続済みかどうかを判断
    tcpiscon p1
    p1 : ソケットID
  • tcpput 文字列を送信。各種プロトコルのリクエストヘッダの送信など。
    tcpput "p1",p2
    p1 : 送信する文字列
    p2 : ソケットID
    tcpput <-> tcpgetl
  • tcpsend データを送信。リクエストボディの送信など。
    tcpsend p1,p2,p3,p4
    p1 : 送信するデータが格納されている変数
    p2 : データのオフセット
    p3 : データのサイズ
    p4 : ソケットID
    tcpsend <-> tcprecv
  • tcpgetl ソケットから一行受信。レスポンスヘッダの受信。
    tcpgetl p1,p2,p3
    p1 : 文字列を受信する変数
    p2 : 最大受信サイズ(64)
    p3 : ソケットID
    tcpgetl <-> tcpput
  • tcprecv ソケットからデータを受信。
    tcprecv p1,p2,p3,p4
    p1 : 受信データを格納する変数
    p2 : 受信オフセット
    p3 : 受信最大サイズ
    p4 : ソケットID
    tcprecv <-> tcpsend

実習サンプル

  • 接続部
    host = "yahoo.co.jp":port = 80
            tcpopen sock,host,port
            if stat:dialog "tcpopenに失敗",1 : end
    *@
            tcpiscon soc
            if stat=0 : wait 1 : goto *@b
            if stat>1 : tcpclose sock : dialog "接続に失敗",1 : end
            if stat=1 : mes "接続完了"
    
    接続はこれだけです。sockは空の数値型変数,hostはyahoo.co.jpのような文字列,portはhttp標準なら80にします。
  • リクエストヘッダ送信部
    page = "/index.html"
            tcpput "POST " + page + " HTTP/1.1\n",sock
            tcpput "Host: " + host + ":" + port+"\n",sock
            tcpput "Connection: close\n",sock
            tcpput "\n",sock
    
    接続部からの続きです。本当に最低限必要なリクエストだけ送るとこうなります。
    例では http://yahoo.co.jp/index.html にアクセスしていることになります。
    Connection: closeは現時点ではお約束だと思って入れておいてください。
    最後に空の一行を送ることで「リクエストは以上だよ〜」という合図を出しています。
  • レスポンスヘッダ受信部
    repeat
            wait 1:tcpgetl buf,64,sock
            if stat!0 : break
    loop
    mes buf
    
    ヘッダを送信したらすぐに返事を待ちます。ほとんど一瞬でレスポンスが帰ってくるので、接続がつながっているかどうかソケットを調べたりする必要はありません。
    上のスクリプトを実行する前に、実際のサンプルを見てください。

    HTTP/1.1 200 OK
    Date: Wed, 04 May 2005 05:59:56 GMT
    P3P: policyref="http://privacy.yahoo.co.jp/w3c/p3p.xml", CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV"
    Cache-Control: private
    Pragma: no-cache
    Connection: close
    Content-Type: text/html;charset=euc-jp
     

    これがレスポンスヘッダですが、よく見ると一番下には一行改行があります。(ここでは空行だとわかるように全角スペースを入れてますが無視してください)
    これは「レスポンスヘッダはここまでですよ〜」という区切りになっています。
    (厳密に言うと空行が2行くらいあったりすることもあります。)
    そして実際にその空行の次の行から本文になっています。だんだんつかめてきたんじゃないでしょうか。

    <html>
    <head>
    <title>Yahoo! JAPAN</title>
    <STYLE TYPE="text/css">
    .spacer { line-height: 110%; }
    .spacer1 {line-height: 115%; }
    </STYLE>
    </head>...以後省略

    もう一度サンプルに戻りましょう。 内側のループでは一行ずつひたすら受信しています。
    最初のmes bufでは"HTTP/1.1 200 OK"、次が"Date: Wed, 04 May 2005 05:59:56 GMT"という具合に表示されていくはずです。
    では、レスポンスヘッダの終わりを見つけるには??
    repeat
            repeat
                    wait 1:tcpgetl buf,64,sock
                    if stat!0 : break
            loop
            mes buf
            if buf = "":mes "空":break
    loop
    
    こうすれば、空行を発見したらすぐ外側のループから抜けれます。
    これの応用でレスポンスステータス "HTTP/1.1 200 OK" を調べたりできます。
    (詳しく言うと、外ループ内でbufについてHTTPという文字を毎回instrで検索し、見つかったらstrmidを使って9文字目から3文字取り出すと"200"のようになりますね。)
    少しレスポンスヘッダについては詳しく扱いましたが、ここがわかればあとは楽勝です。
  • レスポンスボディ受信部
    sdim body,1024000
            repeat
                    tcprecv body,0,con_l,soc
                    if stat!0 : break
                    wait 1
            loop
    notesel body
    notesave "ahya.txt"
    
    ヘッダ受信部の外ループから抜けて、すぐボディを受信します。
    1MB変数を確保していますが、本当はレスポンスヘッダにボディのサイズがちゃんとかいてあるので、それを見て変数のサイズを決めるのがベターです。
    (あまり大きい場合は一時的にファイルに書き出したりしないとダメです。特にHSPは大きいデータの処理が苦手です。)
    tcprecvのstatが0以外になると、受信完了ということになります。(dialog bodyとかやらないようにしてくださいねw)

以上でPcbnet2を使ったhttpクライアントの説明を終わります。
上記のサンプルでは、本当に最低限の事しかやってません。変数の確保もちゃんとやってないので、実際に作っていくときには、バッファオーバーフローを起こしたりしないように設計してください。
あ、ちなみにPcbnet2ってまだベータ版らしいので、配布したりしないようにということです。
Pcbnet1も使い方は基本的に同じで、サンプルも多いので試してみましょう。

ノシ