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も使い方は基本的に同じで、サンプルも多いので試してみましょう。
ノシ
|