Socket Debuggerを使ってみる! ポート:12!POSTの実装に向けて [NETWORK]
SocketDebugger
こことか、 https://www.udom.co.jp/sdg/
こことか、 http://sdg.ex-group.jp/lua.html
をまず見てね!
内部処理を文字列で行うのか?テーブルで行うのか?どっちが得なんだよ!って事でテーブルで処理する事とします。
なんかあれですね、ファイル書き込みにappendモードが無いので受信データを一旦全部テーブルに保存している訳です。ファイル受信試験で数十kbyteのファイルはイイですが、ちょっと大きな、と言っても4Mbyte程度のjpgですがね、メモリが足りなくなってスクリプトの実行エラーが起きますね。
でも同じJPGファイルの送信時には発生しないのは謎ですね。
あとあれですね、全体的に転送が重いので、細かく多量の処理をするのではなく、こうまとまった受信データをいっきに処理したい場合は、内部プログラム受信バッファサイズを大きくとってしまいましょう!と言う話でやんす。
ソース全文
※、わたしあれ、正規表現さっぱりですわ!
こことか、 https://www.udom.co.jp/sdg/
こことか、 http://sdg.ex-group.jp/lua.html
をまず見てね!
内部処理を文字列で行うのか?テーブルで行うのか?どっちが得なんだよ!って事でテーブルで処理する事とします。
なんかあれですね、ファイル書き込みにappendモードが無いので受信データを一旦全部テーブルに保存している訳です。ファイル受信試験で数十kbyteのファイルはイイですが、ちょっと大きな、と言っても4Mbyte程度のjpgですがね、メモリが足りなくなってスクリプトの実行エラーが起きますね。
でも同じJPGファイルの送信時には発生しないのは謎ですね。
あとあれですね、全体的に転送が重いので、細かく多量の処理をするのではなく、こうまとまった受信データをいっきに処理したい場合は、内部プログラム受信バッファサイズを大きくとってしまいましょう!と言う話でやんす。
ソース全文
--------------------------------------------- -- 接続完了通知 --------------------------------------------- function OnConnected() Logput(1,'OnConnected') recvHttpTable = {} -- 受信データの一時格納用 recievedContentTable = {} -- HTTP文の内容格納用 recievedUrlStr = "" -- HTTP文のURL contentLength = 0 -- HTTP文の内容の取り込むべきサイズ operationCode = 0 -- 処理コード return 0 end --------------------------------------------- -- 送信ボタン押下 --------------------------------------------- function OnSendPush() Logput(1,'OnSendPush') a = GetEditorData() SendData(a) return 0 end --------------------------------------------- -- タイマー通知 --------------------------------------------- function OnTimer(id) Logput(1,'OnTimer') return 0 end --------------------------------------------- -- 受信通知 -- 0x0D is CR,0x0A is LF --------------------------------------------- function OnReceive(recv) Logput(1,'OnReceive') if operationCode == 0 then -- 初期状態? recvHttpTable = TableCat( recvHttpTable, recv ) -- 一時格納用テーブルに受信データを保存 if #recvHttpTable < 4 then return 0 end -- 配列の長さを確認 local head local body head,body = getHttpHeader( recvHttpTable ) -- 一時格納用テーブルからheaderとbodyに分ける if head ~= nil then -- headerに内容が入っている時 httpRequest( head, body ) -- HTTPリクエスト処理 if operationCode == 200 then -- 処理コード別の処理 Disconnect() elseif operationCode == 400 then Disconnect() elseif operationCode == 404 then Disconnect() elseif operationCode == 405 then Disconnect() else end else -- 受信はしたが、HTTP文の全てを受け取った訳ではない場合もある return 0 end elseif operationCode == 201 then recievedContentTable = TableCat( recievedContentTable, recv ) -- HTTP文の内容格納用テーブルに受信データを保存 if #recievedContentTable >= contentLength then -- 全て内容を受信できた場合 methodPost( recievedUrlStr, recievedContentTable ) -- method postの実行 Disconnect() end end return 0 end --------------------------------------------- -- 切断通知 --------------------------------------------- function OnDisConnected() Logput(1,'OnDisConnected') Disconnect() return 0 end --------------------------------------------- -- http request --------------------------------------------- function httpRequest( head, body ) local header = CharFromTbl( head ) -- 引数headの内容を文字列に変換 local headerLine = strSplit( header, "\r\n" ) -- 一行目を取得 local line1 = strSplit( headerLine[1], " " ) -- 一行目をスペースで区切る local methodStr = line1[1] -- 最初の単語 local urlStr = line1[2] -- 2番目の単語 local httpVersionStr = line1[3] -- 3番目の単語 recievedUrlStr = urlStr -- 大域変数にも保存 if strCmp( methodStr, 'GET' ) == 0 then -- GETの場合 local fileData = {} local mimeType = "" fileData, mimeType = methodGet( urlStr ) -- 構文解析して要求されたファイルデータとmime typeを返す if fileData ~= nil and mimeType ~= "" then index200( fileData, mimeType ) -- ファイル返信処理 operationCode = 200 -- 処理コード else index404() -- 該当ファイルが見つからない場合 operationCode = 404 -- 処理コード end elseif strCmp( methodStr, 'PUT' ) == 0 then -- PUTの場合 index405() -- 該当METHODが許されていない場合 operationCode = 405 -- 処理コード elseif strCmp( methodStr, 'POST' ) == 0 then -- POSTの場合 contentLength = 0 -- HTTP文の内容の取り込むべきサイズを一旦0にする for i = 1, #headerLine do -- headerの行数分ループ local compStr = "Content-Length:" -- 探したいのはContent-Length if strNCmp( headerLine[i], compStr, #compStr ) == 0 then -- 文字列の比較 local str = strSplit( headerLine[i], " " ) -- スペースで文字列を分割 contentLength = tonumber( str[2] ) -- 2番目の単語を数値に変換 break end end if contentLength > 0 then -- ヘッダーからContent-Lengthを取得できたなら if #body > 0 then -- 引き続きコンテンツが存在する? if #body >= contentLength then -- 全てのコンテンツを受信済み? methodPost( urlStr, body ) -- method postの実行 operationCode = 200 -- 処理コード else -- 全てのデータの受信が完了していないとき recievedContentTable = TableCat( recievedContentTable, body ) -- 受信コンテンツ格納用テーブルに追加保存 operationCode = 201 -- 処理コード end end else -- 構文解析失敗? operationCode = 200 -- 処理コード end elseif strCmp( methodStr, 'DELETE' ) == 0 then -- DELETEの場合 index405() -- 該当METHODが許されていない場合 operationCode = 405 -- 処理コード else index400() -- 不正なリクエスト operationCode = 400 -- 処理コード end end --------------------------------------------- -- method get --------------------------------------------- function methodGet( urlStr ) local file = {} local methodTbl = { { url = "/", path = "D:\\temp\\index.html", mime = "text/html" }, { url = "/index.html", path = "D:\\temp\\index.html", mime = "text/html" }, { url = "/index.htm", path = "D:\\temp\\index.html", mime = "text/html" }, { url = "/favicon.ico", path = "D:\\temp\\favicon.ico", mime = "image/png" }, { url = "/text.txt", path = "D:\\temp\\text.txt", mime = "text/plain" }, { url = "/photo1.jpg", path = "D:\\temp\\photo1.jpg", mime = "image/jpeg" }, { url = "/image1.png", path = "D:\\temp\\image1.png", mime = "image/png" }, { url = "/image2.bmp", path = "D:\\temp\\image2.bmp", mime = "image/bmp" }, { url = "/test.csv", path = "D:\\temp\\test.csv", mime = "text/csv" }, -- { url = "/test.bin", path = "D:\\temp\\test.bin", mime = "application/octet-stream" }, } for i = 1, #methodTbl do if strCmp( urlStr, methodTbl[i].url ) == 0 then file = FileRead( methodTbl[i].path ) return file, methodTbl[i].mime end end return nil,"" end --------------------------------------------- -- method post --------------------------------------------- function methodPost( urlStr, contents ) local path = "D:\\temp\\test" -- 保存先のフォルダーを指定 path = path .. strReplace( urlStr, "/", "\\" ) -- バックスラッシュを円マークに置換 Logput( 1, path ) FileWrite( contents, path ) -- テーブルの内容をファイルに書き込む end --------------------------------------------- -- http request status code = 200 --------------------------------------------- function index200( data, mimeType ) local contentLength = #data local contentHeader = 'HTTP/1.1 200 OK\r\n' .. 'Server: SocketeEbugger Web Server/ ver.0.1\r\n' .. 'Content-Type: ' .. mimeType .. ' charset=UTF-8\r\n' .. 'Content-Length: ' .. contentLength .. '\r\n' .. 'Connection: close\r\n\r\n' SendData( contentHeader ) SendData( data ) end --------------------------------------------- -- http request status code = 404 --------------------------------------------- function index404() local contentHeader = 'HTTP/1.0 404 Not Found\r\n' .. 'Connection: close\r\n\r\n' .. '<html><head><title>404 Not Found</title></head>\r\n' .. '<body>\r\n' .. '<h1>Not Found</h1>\r\n' .. '</body></html>\r\n' SendData( contentHeader ) end --------------------------------------------- -- http request status code = 400 --------------------------------------------- function index400() local contentHeader = 'HTTP/1.0 400 Bad Request\r\n' .. 'Connection: close\r\n\r\n' .. '<html><head><title>400 Bad Request</title></head>\r\n' .. '<body>\r\n' .. '<h1>Bad Request</h1>\r\n' .. '</body></html>\r\n' SendData( contentHeader ) end --------------------------------------------- -- http request status code = 405 --------------------------------------------- function index405() local contentHeader = 'HTTP/1.0 405 Method Not Allowed\r\n' .. 'Connection: close\r\n\r\n' .. '<html><head><title>405 Method Not Allowed</title></head>\r\n' .. '<body>\r\n' .. '<h1>Method Not Allowed</h1>\r\n' .. '</body></html>\r\n' SendData( contentHeader ) end --------------------------------------------- -- compare string A and string B. --------------------------------------------- function strCmp( stringA, stringB ) local strLen = string.len( stringA ) if strLen ~= string.len( stringB ) then return -1 end for i = 1, strLen do if string.byte( stringA, i ) ~= string.byte( stringB, i ) then return -1 end end return 0 end --------------------------------------------- -- compare string A and string B. --------------------------------------------- function strNCmp( stringA, stringB, n ) if n <= 0 then return -1 end for i = 1, n do if string.byte( stringA, i ) ~= string.byte( stringB, i ) then return -1 end end return 0 end --------------------------------------------- -- divide string by ts and enter table. -- https://qiita.com/peg/items/c472f7a7d9fcca1b5cb7 -- https://symfoware.blog.fc2.com/blog-entry-455.html --------------------------------------------- --[[ function strSplit(str, ts) -- 引数がないときは空tableを返す if ts == nil then return {} end local t = {} ; i=1 for s in string.gmatch(str, "([^"..ts.."]+)") do t[i] = s i = i + 1 end return t end ]] function strSplit( str, delim ) -- Eliminate bad cases... if string.find(str, delim) == nil then -- return { str } return nil end local result = {} local pat = "(.-)" .. delim .. "()" local lastPos for part, pos in string.gfind(str, pat) do table.insert(result, part) lastPos = pos end table.insert(result, string.sub(str, lastPos)) return result end --------------------------------------------- -- ASCIIテーブルをコード変換後に文字列化 -- -- ASCIIの例 -- 入力: { 0x30, 0x31, 0x32 } -- 返値: "012" -- http://amlaid.air-nifty.com/blog/2015/10/serial-debugger.html -- 0x0D is CR,0x0A is LF --------------------------------------------- function CharFromTbl(tbl) tblChar = {} for i=1, #tbl do if tbl[i] == 0x0D or tbl[i] == 0x0A then tblChar[i] = string.char(tbl[i]) else tblChar[i] = string.char(tbl[i]) end end return table.concat(tblChar) end --------------------------------------------- -- replace string to tr from ts and enter table. --------------------------------------------- function strReplace( str, before, after ) local str,num = string.gsub( str, before, after ) return str end --------------------------------------------- -- get http header from table -- CR is 0x0D LF is 0x0A --------------------------------------------- function getHttpHeader( tbl ) local header = {} local body = {} local tblLen = #tbl local index = 1 for i = 1, tblLen - 3 do if tbl[ i + 0 ] == 0x0D and tbl[ i + 1 ] == 0x0A and tbl[ i + 2 ] == 0x0D and tbl[ i + 3 ] == 0x0A then break else header[i] = tbl[i] index = index + 1 end end if index > tblLen - 3 then return nil,nil end for i = 1, tblLen do body[i] = tbl[ i + index + 3 ] end return header,body end
※、わたしあれ、正規表現さっぱりですわ!
M5Stick ミニ開発キットESP32 1.3'OLEDオプションのブザーIRトランスミッタMpu9250
- 出版社/メーカー: M5Stack
- メディア: