python – 从espduino超时向Flask发布
我正在玩一个
esp8266,为一个带有
this library的Arduino提供WiFi.我把它设置为POST到
Pushover以及
requestbin,在调试输出和这些工具的界面之间,我可以验证请求数据是正确发布,esp8266 / arduino单元的响应状态代码正确显示200.
我想测试设置的可靠性,所以我想我会转向Flask.我将来自espduino的100个请求发送到for循环到运行在0.0.0.0:5000的Flask应用程序. POST包含一个测试字符串(试图粗略地衡量简单的数据完整性,确保字符串未被破坏)以及正在发送的循环数(例如,第一个循环为0 …最后一个为99) . Flask会跟踪这些请求并更新其输出,以显示哪些请求正确通过,哪些请求未通过. 设置工作正常,除了一件事:模块在每个请求后超时.每个POST似乎都有效,Flask会相应地更新输出,但espduino会为每个请求花费整整5秒(默认超时),并说它的响应代码为0. 所以重申一下情况:我的espduino设置正确POST并从requestb.in和pushover.net获得200响应,但是我的本地Flask服务器POST然后超时. WHYT: >确保all form data is read by Flask – >没有不同 我已经花了几天时间研究这个和not made much progress.我今天取得的最大突破是,如果我把我的gunicorn / Flask设置放在nginx后面,我可以成功发布并获得200个响应,而不会更改espduino代码,所以我确定Flask有或正在做的事情(我担心它可能是espduino处理IP地址与域名的关系,但我认为这可以解决这个问题). 我尝试过的设置摘要: > POST到requestb.in – > POST工作,200响应,没有超时 当前代码: from flask import Flask,request,make_response from datetime import datetime app = Flask(__name__) ESPDUINO_IP = 'XXX.XXX.XXX.XXX' INCOMING_TEST_STRING = 'This is my espduino test string!' incoming_requests = [] with open('results.txt','w') as f: f.write("Test run start: {}n".format(datetime.now())) @app.route('/api',methods=['GET','POST']) def count_requests(): if request.method == 'POST': form = request.form incoming_ip = request.remote_addr if incoming_ip == ESPDUINO_IP and form['test_string'] == INCOMING_TEST_STRING: test_num = int(form['test_num']) incoming_requests.append(test_num) msg = "All is peachy!" with open('results.txt','a') as f: f.write("{:02d}: {}n".format(test_num,datetime.now())) else: msg = "Hey,you're not the espduino!<br>" msg += str(len(incoming_requests)) + " requests so far.<br>" missing = set(range(100)) - set(incoming_requests) msg += "Missing: {}<br>".format(','.join(map(str,missing)) if missing else "None!") msg += '<br>'.join(map(str,incoming_requests)) resp = make_response('{"this": "that"}') resp.headers['Content-Type'] = "application/json" return resp # return "<html><body>{}</body></html>".format(msg) if __name__ == '__main__': app.run(host='0.0.0.0',debug=True) 这是espduino的POST看起来像: $nc -l 5000 POST /api HTTP/1.1 Host: XXX.XXX.XXX.XXX Content-Length: 55 Connection: close Content-Type: application/x-www-form-urlencoded User-Agent: ESPDRUINO@tuanpm test_string=This is my espduino test string!&test_num=0 与curl -X POST -d相比’test_string =这是我的espduino测试字符串!& test_num = 0’localhost:5000 / api: $nc -l 5000 POST /api HTTP/1.1 Host: localhost:5000 User-Agent: curl/7.43.0 Accept: */* Content-Length: 55 Content-Type: application/x-www-form-urlencoded test_string=This is my espduino test string!&test_num=0 很想听听有关可能发生的事情的任何想法.我想知道这可能是一个WSGI问题吗? 2015年8月31日更新: 我仍然没有想到这一点,但这绝对不是Flask特有的问题.正如我上面提到的,我还使用CherryPy以及python3 -m http.server –bind 0.0.0.0 5000(以及将espduino代码更改为GET /)以及ruby -run复制了超时. -e httpd.我仍然不明白为什么nginx,requestbin等服务它没有问题. 为了回应@ Miguel关于HOST标头没有端口的评论,我正在努力分支并构建固件来改变这一点,但与此同时我将客户端主机和端口硬编码为一个小的HTTP服务器脚本,没有运气. from http.server import BaseHTTPRequestHandler,HTTPServer class MyServer(BaseHTTPRequestHandler): # protocol_version = 'HTTP/1.1' # close_connection = True def _set_headers(self): self.send_response(200) self.send_header('Content-type','text/html') self.end_headers() def do_GET(self): self._set_headers() self.wfile.write(b"<html><body><h1>hi!</h1></body></html>") def do_HEAD(self): self._set_headers() def do_POST(self): self.client_address = ("192.168.0.4",5000) self._set_headers() self.wfile.write(b"<html><body><h1>POST!</h1></body></html>") # import pdb; pdb.set_trace() def run(server_class=HTTPServer,handler_class=MyServer,port=5000): server_address = ('0.0.0.0',port) httpd = server_class(server_address,handler_class) print('Starting httpd...') httpd.serve_forever() if __name__ == "__main__": run() 查看tcpdump,看看我是否能找到工作(nginx)和非工作网络数据之间的任何区别.到目前为止还没有找到任何东西,但我也是这个工具的新手. 2015年9月8日更新 仍然没有想到这一点,但看起来tcpdump在nginx和Python服务器之间存在显着差异.这是一个示例POST和响应 – 为了清楚起见,我已经用ESPDUINO_IP和OSX_IP替换了IP,并清理了周围的ACK调用等.我需要调查为什么Python响应被那个奇数行中断 – 我检查了10个连续的POST / Response对,并且每个Python响应都被中断了(在完全相同的地方),并且没有nginx响应是,所以我想知道这可能是问题. (另外,正如您所看到的,在本轮测试中,我已将响应主体更改为文本而不是JSON – 结果没有变化.) nginx(作品) POST /api HTTP/1.1 Host: OSX_IP Content-Length: 29 Connection: close Content-Type: application/x-www-form-urlencoded; charset=utf-8 User-Agent: espduino@n8henrie test_string=simple&test_num=0 09:16:04.079291 IP OSX_IP.commplex-main > ESPDUINO_IP.49146: Flags [P.],seq 1:183,ack 211,win 65535,length 182 HTTP/1.1 200 OK Server: nginx/1.8.0 Date: Mon,31 Aug 2015 15:16:04 GMT Content-Type: text/html; charset=utf-8 Content-Length: 26 Connection: close <html><body></body></html> 烧瓶(超时) POST /api HTTP/1.1 Host: OSX_IP Content-Length: 29 Connection: close Content-Type: application/x-www-form-urlencoded; charset=utf-8 User-Agent: espduino@n8henrie test_string=simple&test_num=3 09:00:19.424086 IP OSX_IP.commplex-main > ESPDUINO_IP.48931: Flags [P.],seq 1:18,length 17 HTTP/1.0 200 OK 09:00:36.382125 IP OSX_IP.commplex-main > ESPDUINO_IP.48931: Flags [FP.],seq 18:181,length 163 E....F@.@..,...e.......#...k..S.P.......Content-Type: text/html; charset=utf-8 Content-Length: 26 Server: Werkzeug/0.10.4 Python/3.4.3 Date: Mon,31 Aug 2015 15:00:36 GMT <html><body></body></html> 在我看来,Python出于某种原因将响应分成两部分,例如:长度为17的一部分和长度为163的另一部分,与nginx的长度为182的单一响应相比. 2015年9月10日更新 有趣的是,如果我通过mitmproxy运行它,一切都按预期工作 – 甚至直接到没有nginx或gunicorn的Flask应用程序.一旦我删除了mitmproxy,它就会回到上面的超时时间. 解决方法
仍然没有解决问题,但我想我可能已经弄明白是什么导致了它.毕竟不是Flask问题.
不幸的是,这似乎是esp_bridge库的一个错误,它的固件espduino在esp8266中使用.请原谅可能不正确的术语,但是由于某种原因,我可以告诉它似乎并没有加入TCP数据包.产生分解为单独TCP数据包(例如Flask)的HTTP响应的服务器失败,而tcpdump可以验证nginx和mitmproxy正在加入拆分TCP数据包并在单个数据包中返回响应,这就是他们正在工作的原因. https://github.com/tuanpmt/esp_bridge/issues/10 更新20160128 我今天和found a workaround重新讨论了这个问题.虽然理想的解决方案是修复esp_bridge以重新组合多数据包响应,只要响应非常小,就可以强制Flask在单个数据包中写入响应. from werkzeug.serving import WSGIRequestHandler # Your Flask code here... if __name__ == "__main__": WSGIRequestHandler.wbufsize = -1 app.run() (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |