[HSP3]hspsockでHTTPサーバを作る

本当にHTTPサーバを作りたいならば、JavaServletをお勧めします。

作り方はとっても簡単、仕様通りの要求を受けて、仕様通りの応答をするだけです。
hspsockならTCP辺りは全部やってくれるので、仕様見ながら応答プログラムを設計するだけ。
HTTPメッセージの解説はとほほのWWW入門がお勧めです。

動作はHSPを実行させ、適当なウェブブラウザから「http://localhost:20111」へジャンプすれば確認できます。localhostは自分のPCを示す、コロンはポート番号。ポート解放さえすれば、他PCからアクセス可能でしょう。多分。
適当なディレクトリを参照しようとすると無地の404を返します。そういうプログラムを記述しました。

logmesを多用しています。「メニューバー→HSP→Debugウィンドゥを表示」で有効にすると、プログラム実行時、デバッグウィンドウを表示できます。


#include "hspsock.as"

#const TCPPORT 20111

txresponse=""

sdim buff,5000 : buffsize=0
;rev_type="","",""
;rev_connect=""
;rev_accept=""
;rev_agent=""
;rev_encode=""
;rev_lang=""
;rev_ref=""
;rev_data=""

// 初期化
sockmake 0,TCPPORT
if stat : dialog "sockmake error"+stat : end
onexit *exit

mes "make:"

flreset=0
repeat
// Listen.
sockwait 0,0
title ""+stat

if (stat==0) {
flreset=0
logmes "[sockwait]:0"

// 取得待ち
sockcheck 0
if stat : mes "sockcheck break:"+stat : continue

// 読み取り
sockget buff,5000,0
mes "[sockget]:"+stat
buffsize=stat

// debugウィンドウに表示
logmes "[sockget]"
logmes ""+buff

// 解析
gosub *bufana

// URL整形
url=""
getstr url,rev_type.1,0,'?'
url=getpath(url,16)

// 返信
if (url=="/"){
txresponse="<head><body><h2>index</h2><a href=\"time\">time</a>,<a href=\"info\">info</a>,<a href=\"form\">form</a></body></html>"
txresponse=strf("HTTP/1.1 200 OK\nContent-Length: %d\nContent-Type: text/html\n\n",strlen(txresponse))+txresponse
sockput txresponse,0
}else:if (url=="/time"){
txresponse=strf("<head><body><h2>%02d:%02d:%02d</h2></body></html>",gettime(4),gettime(5),gettime(6))
txresponse=strf("HTTP/1.1 200 OK\nContent-Length: %d\nContent-Type: text/html\n\n",strlen(txresponse))+txresponse
sockput txresponse,0
}else:if (url=="/info"){
txresponse =strf("<head><body><table border=1><tr><td>type</td><td>%s</td></tr><tr><td>referer</td><td>%s</td></tr><tr><td>user_agent</td><td>%s</td></tr>",rev_type.0,rev_ref,rev_agent)
txresponse+=strf("<tr><td>data</td><td>%s</td></tr></table><textarea rows=12 cols=60>%s</textarea></body></html>",rev_data,buff)
txresponse=strf("HTTP/1.1 200 OK\nContent-Length: %d\nContent-Type: text/html\n\n",strlen(txresponse))+txresponse
sockput txresponse,0
}else:if (url=="/form"){
txresponse ="<head><body><form method=\"POST\" action=\"info\">1<input type=\"text\" name=\"key1\">2<input type=\"text\" name=\"key2\">"
txresponse+="<input type=\"submit\"></form></body></html>"
txresponse=strf("HTTP/1.1 200 OK\nContent-Length: %d\nContent-Type: text/html\n\n",strlen(txresponse))+txresponse
sockput txresponse,0
}else{
sockput "HTTP/1.1 404 Not Found\nConnection: close\nContent-Type: text/html\n\n",0
}
logmes "[sockput]"+stat

}else:if (stat>1){
mes "[sockwait]ERROR:"+stat
//break
if (flreset>2) : mes "ERROR." : goto *exit
flreset++
// リセット
sockclose 0
sockmake 0,TCPPORT
if stat : dialog "sockmake error"+stat : goto *exit
mes "make:"+stat
}else{
flreset=0
}
wait 15

// tabキーを押すと画面リセット
stick key
if key&1024 : cls
loop
*exit
sockclose 0
mes "sockclosed"
onexit 0
stop

// 受信情報解析
*bufana
// 他にも種類は山ほどある
rev_type="","","" // GET ADDR HTTP
rev_connect="" // Connection:
rev_accept="" // Accept:
rev_agent="" // User-Agent:
rev_encode="" // Accept-Encoding:
rev_lang="" // Accept-Language;
rev_ref="" // Referer:
rev_data="" // data

notesel buff
noteget a,0
split a," ",rev_type // 始めの1行

repeat notemax-2,1
noteget a,cnt
getstr b,a,0,':'
i=strsize
b=getpath(b,16)
switch b // 小文字化して比較
case "host"
swbreak
case "connection"
rev_connect=strmid(a,i,1024)
swbreak
case "accept"
rev_accept=strmid(a,i,1024)
swbreak
case "user-agent"
rev_agent=strmid(a,i,1024)
swbreak
case "accept-encoding"
rev_encode=strmid(a,i,1024)
swbreak
case "accept-language"
rev_lang=strmid(a,i,1024)
swbreak
case "referer"
rev_ref=strmid(a,i,1024)
swbreak
default
logmes "? ->"+a
swbreak
swend
loop

// postメッセージなど
noteget a,notemax-1
rev_data=a

noteunsel

return


やっていることは、ウェブブラウザからの要求が届き、sockget命令によって変数buffに突っ込まれるので解析、応答メッセージを作成してsockputするだけです。
自分で作る上で引っかかったのはsockwaitは接続要求を待つのであって、データが届いたとは限らないんですなぁ。sockcheckを挟まないと長時間応答なしになります。HSPのサーバサンプルにはsockcheck入ってなかったんですよお!

是非HSP愛に溢れる方はHSPでHTTPサーバ構築なんてどうでしょう。

2015/04/26 修正
スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

tag : HSP3 通信制御

[MATLAB/Simulink] Simulinkモデルがターゲットハードウェア上で動作しない、常に出力端子がLow、実行時間が進んでいない

このような現象
・シミュレーションは正しく動作する、波形等も正しい結果が出る。
・定数ブロックとハードウェア入出力端子ブロックを直結しただけのモデルで実行すると正しい出力が出る。
・エクスターナルモードで確認すると、T=0.00になっており、実行していない

気が付くまでに時間がかかったのですが、連続関数が混じってただけでした。
例えば、Sineはサンプル単位で指定。など。
シミュレーションは普通に動作してしまうので原因の特定が難しい。
どこにもエラー吐かないので厄介でしたね。

テーマ : プログラミング
ジャンル : コンピュータ

tag : Simulink

[Minecraft1.8]スコアボードのスコアをレッドストーン信号に変換する その2

[Minecraft1.8]スコアボードのスコアをレッドストーン信号に変換する、レッドストーン信号をスコアボードのスコアに変換する
これの続編です。

前回の変換回路(回路なのか?)は0.4秒程度という恐ろしい速さで変換できました。大量にスコアボードを展開することを気にしなければ、最良の方法かと思います。

ただ、同じ処理を何度も書いていると、つい1つに纏めたくなってくる。えぇ。纏めちゃいました。

論理回路だと思ってたレッドストーンが気が付けば言語的な…

2014-11-25_17.png

細長いですが。
ディスプレイ部分はスタック構造になっています。
クォーツブロックの箇所は入力ボタンで、パルス(短いON信号)を生成するようにしてあります。入力信号をループさせるため。

アルゴリズム(testScore00を表示させたい)
1.Cを8にする。(8はビット数)
2.C> 0 を満たす間3~6をループする
 3.testScore00を2で割った余りをXに入れる。
 4.X=0であればOFFを、X=1であればONをディスプレイスタックにプッシュする。
 5.testScore00を2で割る。
 6.Cから1引く。

実際に実装する上では、testScore00を弄るためコピーを用意したり、2を保持するスコアボードも必要等厄介なので、いろいろ盛り込みます。

#temp0はダミーユーザ。
[Tick-1] // スコアボード作成
/scoreboard players operation #temp0 testScore00 = @p testScore00 // ダミーユーザにスコアをコピー
/scoreboard objectives add testScore00a dummy // ダミースコア
/scoreboard objectives add times dummy // 回数
/scoreboard objectives add num2 dummy // 2
[Tick-2] // 初期値セット
/scoreboard players set #temp0 times 8 // 16にしたり4にしたりすることもできる
/scoreboard players operation #temp0 testScore00a = #temp0 testScore00
/scoreboard players set #temp0 num2 2
[Tick-3]
/scoreboard players operation #temp0 testScore00a %= #temp0 num2 // 剰余
/scoreboard players remove #temp0 times 1
[Tick-4]
/scoreboard players test #temp0 testScore00a 1 [ディスプレイへ]
/scoreboard players test #temp0 times * 0 [終了処理スイッチへ]
/scoreboard players test #temp0 times 1 [ループスイッチへ]
Tick-4の入力信号をディスプレイへ[PUSH]
[ループスイッチ-1]
/scoreboard players operation #temp0 testScore00a = #temp0 testScore00 // testScore00a 復帰
入力信号を[Tick-3]へ
[ループスイッチ-2]
/scoreboard players operation #temp0 testScore00a /= #temp0 num2 // 2で割る
/scoreboard players operation #temp0 testScore00 /= #temp0 num2 // 2で割る
[終了処理スイッチ] // スコアボードの解放
/scoreboard objectives remove times
/scoreboard objectives remove num2
/scoreboard objectives remove testScore00a

フローチャートみたいな図貼りたいのですが画像添付が面倒でな

operation 系統は「AをBで演算した結果をAに入れる」という計算しかできない(すなわちAが上書きされる)ので、必要に応じてバックアップが必要。

ディスプレイの回路部分はリピータの信号保持機能使っています。

tag : Minecraft

[HSP3]フーリエ級数展開プログラミング

なんとなくフーリエ級数展開。式をそのまま移植するだけ。虚数不要だから簡単。
説明は無し。wikipediaとは異なる式を使っていますが・・・。

データ圧縮として実装してみたいです。HSPだと流石に限界か。

定数。
INTEGDIV 積分の微小分
NUM 展開する三角関数の数 10辺りの数にすると級数展開っぽい
TIM 1周期の長さ
SAMPLE 復元させる波形のデータ数
VIEWZOOM 表示倍率(縦)



#const double INTEGDIV 0.01

#const double NUM 100
#const double TIM M_PI*2
#const double SAMPLE 600

;#define ctype func(%1) (sin(%1))
;#define ctype func(%1) ((%1)/TIM)
#define ctype func(%1) (0.0+((%1)>TIM/2)-0.5)
;#define ctype func(%1) (((%1)/TIM)*((%1)/TIM))
;#define ctype func(%1) (expf(-(%1)))
;#define ctype func(%1) (2.0*absf((%1)/TIM-0.5)-0.5)
;#define ctype func(%1) ((1.0-(%1)/TIM)*((%1)>TIM/2))

#const double VIEWZOOM1 300
#const double VIEWZOOM2 100

ddim xa,NUM+1
ddim xb,NUM+1

ddim reFunc,SAMPLE,2

;----------展開
t=0.0
while (t<TIM)
xa.0 += func(t)*INTEGDIV
t+=INTEGDIV
wend
xa.0 = (xa.0)/TIM
repeat NUM,1
t=0.0
while (t<TIM)
xa.cnt += func(t)*2.0*cos(t*2.0*M_PI*cnt/TIM)*INTEGDIV
xb.cnt += func(t)*2.0*sin(t*2.0*M_PI*cnt/TIM)*INTEGDIV
t+=INTEGDIV
wend

xa.cnt = (xa.cnt)/TIM
xb.cnt = (xb.cnt)/TIM
loop

;-------------------------------復元
t=0.0 : c=0
while (c<SAMPLE)
reFunc.c.0=t
reFunc.c.1=xa.0
repeat NUM,1
reFunc.c.1+=xa.cnt*cos(t*2.0*M_PI/TIM*cnt)+xb.cnt*sin(t*2.0*M_PI/TIM*cnt)
loop
t+=INTEGDIV : c++
wend


;-------------------------------表示

line 0,200,640,200

repeat NUM+1

color 255,0,0 : line 3*cnt ,200,3*cnt ,200-VIEWZOOM1*xa.cnt
color 0,255,0 : line 3*cnt+1,200,3*cnt+1,200-VIEWZOOM1*xb.cnt

;logmes strf("f(%8.3f)=%12.6f integ[%12.6f] deriv[%12.6f]",time,f,integ,deriv)

;time+=TIMESTEP
loop
t=reFunc.0.0
fc=reFunc.0.1
repeat SAMPLE-1,1
t2=reFunc.cnt.0
fc2=reFunc.cnt.1
color 192,192,255 : line t*50,200-VIEWZOOM2*func(t),t2*50,200-VIEWZOOM2*func(t2)
color 0,0,255 : line t*50,200-VIEWZOOM2*fc,t2*50,200-VIEWZOOM2*fc2
logmes strf("%8.3f: %8.3f / %8.3f",t2,fc2,func(t2))
t=t2
fc=fc2
loop
stop

テーマ : プログラミング
ジャンル : コンピュータ

tag : HSP3 アルゴリズムとデータ構造

[Minecraft1.8]スコアボードのスコアをレッドストーン信号に変換する、レッドストーン信号をスコアボードのスコアに変換する

1.8でスコアボード系のコマンドも充実しましたし、ひょっとしてこれはいけるのではないか。
これができれば遅延で悩んでた算術回路等の高速化も行けるんじゃないかな。






レッドストーン信号をスコアボードのスコアに変換する

2014-11-05_23_30.png

ちょっと2進数を知っていればすぐ理解できます。
スコアボードを0にして、下位ビットから1,2,4,8...と割り振ればいいんです。

上図の操作は、右から「スコアボード消去」「スコアボード初期化」「2^0桁」「2^1桁」「2^2桁」「2^3桁」「スコアボード書き込み」のボタンになっています。
「スコアボード初期化」をクリックすると、次のコマンドを実行します。スコア作るだけです。
/scoreboard objectives add viewDecimal dummy result
「スコアボード消去」をクリックすると、次のコマンドを実行します。使い終わったら押す奴です。
/scoreboard objectives remove viewDecimal

裏はこうなっており・・・
2014-11-05_23_40.png
「スコアボード書き込み」を押すと、以下のコマンドを実行してからピストンが降ります。0に初期化するんですね。プレイヤーは@aで指定していますが、気にしない。
/scoreboard players set @a viewDecimal 0
ピストンの先のコマンドブロックにはこれ。
/scoreboard players add @a viewDecimal 1
/scoreboard players add @a viewDecimal 2
/scoreboard players add @a viewDecimal 4
/scoreboard players add @a viewDecimal 8
たとえば、「2^0桁」「2^2桁」のレバーがONの状態で「スコアボード書き込み」を実行すれば、1+4=5がスコアviewDecimal にセットされる。






スコアボードのスコアをレッドストーン信号に変換する

下図はスコアボードに37がセットされた状態でボタンを押したもの。37=00100101なので、正しいですね。
2014-11-06_00_01.png
コマンドブロックが多い印象ですが、同じ事書いてるだけです。

考え方はこう。
testScore00の値を出力したい、とする。演算記号a%bはaをbで割った余り、a^bはaのb乗を示す。
0bit目 = (1 <= (testScore00 % 2 ))
1bit目 = (2 <= (testScore00 % 4 ))
2bit目 = (4 <= (testScore00 % 8 ))
nbit目 = (2^n <= (testScore00 % 2^(n+1) ) )

「/scoreboard players operation」というコマンドを使うと剰余が計算できます。わぁすごい。

手順。
1.計算用スコアボードの用意
2.計算用スコアボードの値のセット
3.players operationで演算
4.players testで比較、出力
5.計算用スコアボードの消去

例えばtestScore00から2進数2bit目の値を取り出すには、
Q2 = (4 <= (testScore00 % 8 ) )

コマンドでは、(ダミープレイヤー#temp0 使用)
[1]/scoreboard objectives add num8
/scoreboard objectives add testScore00c
[2]/scoreboard players set #temp0 num8 8
/scoreboard operation #temp0 testScore00c = @p testScore00
[3]/scoreboard operation #temp0 testScore00c %= temp0 num8
[4]/scoreboard players test #temp0 testScore00c 4 「レッドストーン出力」
[5]/scoreboard objectives remove num8
/scoreboard objectives remove testScore00c

operationはスコアボード同士でしか演算ができないので、スコアボードを用意
これを8桁分用意するだけ。






コンパレータやリピータでガリガリやってたのが懐かしいです。応用すれば大規模かつ高速な加算回路も簡単に作れてしまいますね…。

tag : Minecraft

[HSP3]hspでpd制御

現実空間でモータ回したりはしません。

マウスのx座標に追従するプログラムです。
ctrlを押すとユーザが方向キーで操作できます。
レースゲームのNPCカーに応用できるでしょう。

係数の指定は直感で指定するのではなく、vemsimでシミュレートすると便利です。Syhthesimで、パラメータを操作しながらグラフが確認できます。
vemsimは微分方程式が理解できればより効果的に扱えますが、そんなもの知らなくても「バケツに水を注ぐ~」イメージ程度で簡単にモデルが作成できるのがおすすめできる点です。



togglectrl=0

machinepos=0.0
machinevel=0.0
machineacc=0.0

targetpos = 200.0

#const double ACCSTEP 0.25

#const double aiK2 5
#const double aiK3 -80

repeat
redraw 0
color 255,255,255 : boxf

gosub *update

gosub *control

gosub *drawing

redraw 1
wait 2
loop
stop
*update
machinevel+=machineacc
machinepos+=machinevel
machinevel=machinevel*0.99
return

*control
targetpos = mousex

stick key,1|4

if (key&64) {// ctrl
togglectrl=togglectrl^1
}
//if (key&1024) : togglectrl=togglectrl^1 // tab
d=targetpos-machinepos

machineacc=0.0
if (togglectrl){
if(key&1) :machineacc=-ACCSTEP
if(key&4) :machineacc=ACCSTEP
}else{
c= aiK2*d + aiK3*machinevel
if (c<-20) :machineacc=-ACCSTEP
if (c>20) :machineacc=ACCSTEP
}

return
*drawing
color 0,0,0
line 0,300,640,300
boxf machinepos-10,295,machinepos+10,305

pos 0,0
mes "ctrl["+togglectrl+"]"
mes strf("machine(pos:%9.3f/vel:%6.3f/acc:%6.3f)",machinepos,machinevel,machineacc)
mes strf("c:%9.3f",c)

return

テーマ : プログラミング
ジャンル : コンピュータ

tag : HSP3

プロフィール

舞葉(ぶよう)

Author:舞葉(ぶよう)
github.io
はてなブログ(競プロ)

古い記事のソースコードは色分けしていないので、高機能テキストエディタに貼り付けたほうが見やすいかも。

検索フォーム
このブログについて
自分がつまづいた話題、なんとなく書きたいと思ったこと、ググったけど殆ど資料なかったぞオイ な話等をアップする予定。通りすがりでも、参考になっていただければと。プログラムの例外入力、メモリリークは責任負いません。投稿された記事は修正・削除する場合があります。
カテゴリ
タグ

HSP3アルゴリズムとデータ構造c++RubyJavaUnity画像解析C機械学習C#LinuxcodeIQKinectMinecraftTonyuSystemraspberrypiPythonHTML5音声制御Simulinkruby俺ルール通信制御Javascriptシミュレーション

counter-shinobi
固定記事
最新記事
最新コメント
月別アーカイブ
ブロとも申請フォーム

この人とブロともになる

アクセスランキング
[ジャンルランキング]
コンピュータ
1139位
アクセスランキングを見る>>

[サブジャンルランキング]
プログラミング
191位
アクセスランキングを見る>>