ESP32 MicroPython asyncio stream与React Native socket通信失败问题
问题原因分析
- 核心原因:缺失标准HTTP响应头
你React Native端使用fetch发起的是标准HTTP请求,要求服务端返回符合HTTP协议规范的响应格式。之前的同步服务端代码会先发送200 OK状态行、Content-Type、Connection等响应头,再用空行分隔头和响应体最后返回JSON,完全符合HTTP协议要求;但asyncio版本的服务端直接返回JSON字符串,没有任何HTTP头信息,fetch无法识别合法响应,自然解析不到返回的JSON数据。 - 次要原因:请求读取逻辑不符合HTTP协议规范,未主动关闭连接
你当前asyncio服务端用sreader.readline()读取请求,只会拿到HTTP请求的第一行(请求行),没有读完完整的HTTP请求(HTTP请求以连续两个\r\n作为结束标志);且返回响应后没有主动关闭写端,客户端会一直等待响应结束直到超时,进一步导致响应解析失败。
修复方案
修改run_client方法的响应逻辑,补全HTTP响应头,读完完整请求后返回数据并主动关闭连接即可,修改后的参考代码如下:
async def run_client(self, sreader, swriter): self.cid += 1 print('Got connection from client', self.cid) try: # 读取完整HTTP请求,直到遇到空行(HTTP请求结束标志) while True: line = await asyncio.wait_for(sreader.readline(), self.timeout) if line in (b'\r\n', b'\n', b''): break # 构造响应 response = { 'error': 'invalid request', 'status': 'retry' } resp_body = ujson.dumps(response) # 补全所有HTTP响应头 swriter.write(b'HTTP/1.1 200 OK\r\n') swriter.write(b'Content-Type: application/json; charset=utf-8\r\n') swriter.write(f'Content-Length: {len(resp_body)}\r\n'.encode('utf-8')) swriter.write(b'Connection: close\r\n') swriter.write(b'\r\n') # 空行分隔响应头和响应体 # 写入响应体 swriter.write(resp_body.encode('utf-8')) await swriter.drain() except OSError: pass print('Client {} disconnect.'.format(self.cid)) await swriter.wait_closed() print('Client {} socket closed.'.format(self.cid))
内容的提问来源于stack exchange,提问作者srinivasa rao pedada
相关产品推荐
相关产品推荐

