网站规划与建设是什么样的wordpress 建网页
网站规划与建设是什么样的,wordpress 建网页,做门的网站,什么网站做推广效果好1. 问题说明1.1 系统需求某设备管理系统需兼容安卓智能设备与嵌入式RTOS设备#xff0c;两类设备均支持 HTTP 和 TCP 协议。受现场物联网卡限制#xff0c;所有设备只能通过单一地址和端口接入。系统使用 HAProxy 进行流量分发#xff0c;对外统一暴露一个端口#xff0c;内…1. 问题说明1.1 系统需求某设备管理系统需兼容安卓智能设备与嵌入式RTOS设备两类设备均支持 HTTP 和 TCP 协议。受现场物联网卡限制所有设备只能通过单一地址和端口接入。系统使用 HAProxy 进行流量分发对外统一暴露一个端口内部按协议类型分流至不同服务。1.2 问题描述在生产环境中安卓设备调用接口 A 可正常收到响应并执行业务流程而 RTOS 设备调用同样的接口 A 时仅收到响应码00且响应体为空date字段为空。使用 Postman 模拟 RTOS 设备的请求却能正常收到响应。2. 问题分析由于服务端未对两类设备做差异化处理且 Postman 测试正常初步判断问题源于 RTOS 设备侧的 HTTP 客户端实现。安卓设备使用标准 HTTP 框架如 OkHttp而 RTOS 设备采用自研的轻量级 Socket 实现可能在 HTTP 协议头部处理、连接管理或响应解析等方面存在兼容性问题。2.1 RTOS设备与Android设备实现差异分析对比维度Android设备RTOS设备问题影响HTTP库OkHttp/HttpURLConnection手动Socket实现头部完整性差异协议支持HTTP/1.1完整支持可能简化实现缺少必需头部连接管理Keep-Alive自动处理可能固定短连接HAProxy检测失败头部格式RFC规范格式可能格式不规范协议检测不通过编码处理UTF-8自动处理可能编码错误响应解析失败RTOS设备端的请求POST /serxxxxs/xxxs/xxxxxxe HTTP/1.1 Content-Type: application/json; charsetUTF-8 Connection: Keep-Alive Accept:application/json Host: 192.168.xx.xx Content-Length: 44 { pn: xxxxx, sn: xxxxxxxxxxxx }2.2 HTTP协议请求和响应规范2.2.1 HTTP请求头Request Headers2.2.1.1通用头部General Headers头部字段说明示例Connection控制连接状态Connection: keep-aliveConnection: closeCache-Control缓存控制指令Cache-Control: no-cacheCache-Control: max-age3600PragmaHTTP/1.0的缓存控制Pragma: no-cacheDate消息生成的日期时间Date: Tue, 15 Nov 2024 08:12:31 GMT2.2.1.2请求头部Request Headers头部字段说明示例Host服务器的域名和端口HTTP/1.1必需Host: api.example.com:8443User-Agent客户端信息User-Agent: Mozilla/5.0 (Android 10)Accept可接受的响应内容类型Accept: application/json, text/plain, */*Accept-Encoding可接受的编码方式Accept-Encoding: gzip, deflate, brAccept-Language可接受的语言Accept-Language: zh-CN,zh;q0.9,en;q0.8Authorization认证信息Authorization: Bearer token123Cookie发送的CookieCookie: sessionIdabc123; userId456Referer来源页面URLReferer: https://www.example.com/pageOrigin跨域请求来源Origin: https://www.example.com2.2.1.3实体头部Entity Headers头部字段说明示例Content-Type请求体的MIME类型Content-Type: application/json; charsetUTF-8Content-Length请求体的字节长度Content-Length: 348Content-Encoding请求体的编码方式Content-Encoding: gzip2.2.2 HTTP响应头Response Headers2.2.2.1通用头部头部字段说明示例Connection连接状态Connection: keep-aliveCache-Control响应缓存策略Cache-Control: public, max-age3600Date响应生成时间Date: Tue, 15 Nov 2024 08:15:00 GMT2.2.2.2响应头部头部字段说明示例Server服务器软件信息Server: nginx/1.18.0Set-Cookie设置CookieSet-Cookie: sessionIdxyz789; Path/; HttpOnlyLocation重定向目标URLLocation: https://new.example.com/resourceWWW-Authenticate认证要求WWW-Authenticate: Basic realmAccess to site2.2.2.3实体头部头部字段说明示例Content-Type响应体的MIME类型Content-Type: application/json; charsetUTF-8Content-Length响应体的字节长度Content-Length: 1024Content-Encoding响应体的编码方式Content-Encoding: gzipTransfer-Encoding传输编码方式Transfer-Encoding: chunkedContent-Disposition内容处理方式Content-Disposition: attachment; filenamefile.zip2.3 使用python模拟RTOS设备请求2.3.1 请求及结果分析import socket import json import time def debug_device_request(): 带详细调试信息的模拟 host 192.168.XXXX.XXXX port XXXXXXX path /serXXXXX/XXX/XXXXXXXXile # 准备数据 payload {pn: XXXXXXXXXXXX, sn: XXXXXXX} # json.dumps() 的作用将Python对象转换为JSON格式字符串 # 参数1要转换的Python对象字典、列表、字符串等 # 参数2separators - 控制JSON字符串的格式 body json.dumps(payload, separators(,, :)) # 构建请求 headers [ fPOST {path} HTTP/1.1, fContent-Type: application/json; charsetUTF-8, fConnection: Keep-Alive, fAccept: application/json, fHost: {host}, fContent-Length: {len(body)}, , # 空行 body ] request \r\n.join(headers) print( * 50) print(模拟设备请求:) print( * 50) print(request) print( * 50) # 创建socket sock socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 关键配置 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) sock.settimeout(10.0) try: print(f\n1. 连接到 {host}:{port}...) start_connect time.time() sock.connect((host, port)) connect_time time.time() - start_connect print(f 连接成功耗时: {connect_time:.3f}秒) print(\n2. 发送请求...) start_send time.time() # 分步发送以便调试 request_bytes request.encode(utf-8) total_sent 0 chunk_size 1024 while total_sent len(request_bytes): sent sock.send(request_bytes[total_sent:total_sentchunk_size]) if sent 0: raise RuntimeError(Socket连接已断开) total_sent sent print(f 已发送 {total_sent}/{len(request_bytes)} 字节) send_time time.time() - start_send print(f 发送完成耗时: {send_time:.3f}秒) # 等待响应 print(\n3. 等待响应...) time.sleep(0.1) # 给服务器处理时间 # 接收响应 response b start_recv time.time() # 设置接收超时 sock.settimeout(5.0) try: while True: chunk sock.recv(4096) if not chunk: break response chunk print(f 收到 {len(chunk)} 字节累计 {len(response)} 字节) # 如果收到完整HTTP响应可以提前退出 if b\r\n\r\n in response: # 检查是否有Content-Length headers_end response.find(b\r\n\r\n) headers response[:headers_end].decode(utf-8, errorsignore) if Content-Length: in headers: # 解析内容长度 import re match re.search(rContent-Length:\s*(\d), headers) if match: content_length int(match.group(1)) body_start headers_end 4 if len(response) body_start content_length: print( 收到完整响应体) break else: # 没有Content-Length可能是chunked或连接关闭 print( 没有Content-Length头继续接收...) except socket.timeout: print( 接收超时) recv_time time.time() - start_recv print(f\n4. 响应统计:) print(f 总耗时: {recv_time:.3f}秒) print(f 总接收: {len(response)} 字节) if response: print(\n5. 响应内容:) try: response_text response.decode(utf-8, errorsignore) print(response_text[:2000]) # 显示前2000字符 except: print( (无法解码为UTF-8显示前500字节的hex)) print(response[:500].hex()) return response except socket.timeout as e: print(f\n错误: 连接或接收超时 - {e}) except ConnectionRefusedError as e: print(f\n错误: 连接被拒绝 - {e}) except Exception as e: print(f\n错误: {e}) import traceback traceback.print_exc() finally: sock.close() print(\n连接已关闭) # 执行 debug_device_request()执行结果如下发现请求的响应中没有Content-Length和Transfer-Encoding: chunked且有Connection: close。设备端网络层接收到后默认连接断了就不会再处理后续date。2.3.2 RFC规范要求根据RFC 7230 Section 3.3.3HTTP/1.1响应必须满足以下条件之一包含有效的Content-Length头部使用Transfer-Encoding: chunked使用Connection: close但这是针对HTTP/1.0的兼容实际上对于HTTP/1.1如果同时没有Content-Length和Transfer-Encoding: chunked即使有Connection: close也应该被视为格式错误2.3.3 问题发生的具体流程RTOS设备发送请求 → HAProxy接收 → 后端处理 → 返回响应↓Connection: close无Content-Length无Transfer-Encoding↓RTOS设备收到头部后等待...↓服务器关闭连接(Socket EOF)↓RTOS设备应该读到底但在收到close前就返回了↓应用层只收到空的响应体3. 问题解决使用的是HAProxy进行的流量分流3.1 修复HAProxy配置# haproxy_fix.cfg - 确保响应格式正确 backend app_backend mode http # 1. 如果后端没有Content-Length添加它 http-after-response set-header Content-Length %[res.len] if { res.hdr_cnt(Content-Length) eq 0 } # 2. 或者强制使用chunked编码 # http-response set-header Transfer-Encoding chunked if { res.hdr_cnt(Content-Length) eq 0 } # 3. 清理连接头部 http-response del-header Connection http-response set-header Connection close # 4. 确保Date头部存在 http-response set-header Date %[date()] server app1 192.168.1.10:8080 check3.2 修复RTOS设备客户端代码// rtos_client_fix.c - 修复RTOS客户端响应处理 #include stdbool.h #include string.h #include sys/socket.h // 修复的响应读取函数 int read_http_response_fixed(int sock, char* buffer, int buf_size, int timeout_sec) { int total_received 0; bool headers_complete false; int content_length -1; // -1表示未知 bool connection_close false; // 设置超时 struct timeval tv; tv.tv_sec timeout_sec; tv.tv_usec 0; setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, tv, sizeof(tv)); while (total_received buf_size - 1) { // 接收数据 int received recv(sock, buffer total_received, buf_size - total_received - 1, 0); if (received 0) { // 连接关闭或超时 break; } total_received received; buffer[total_received] \0; // 检查头部是否完整 if (!headers_complete) { char* headers_end strstr(buffer, \r\n\r\n); if (headers_end) { headers_complete true; // 解析头部 char* header_start buffer; while (header_start headers_end) { char* line_end strstr(header_start, \r\n); if (!line_end || line_end headers_end) break; // 检查Content-Length if (strncasecmp(header_start, Content-Length:, 15) 0) { sscanf(header_start 15, %d, content_length); } // 检查Connection if (strncasecmp(header_start, Connection:, 11) 0) { if (strstr(header_start, close)) { connection_close true; } } header_start line_end 2; } // 关键修复如果没有Content-Length但有Connection: close if (content_length -1 connection_close) { // 将剩余所有数据读到底 content_length INT_MAX; // 设置为最大值读到底 } } } // 检查是否接收完整 if (headers_complete) { int headers_len strstr(buffer, \r\n\r\n) - buffer 4; int body_received total_received - headers_len; // 如果有明确的Content-Length if (content_length 0 content_length ! INT_MAX) { if (body_received content_length) { break; // 接收完整 } } // 如果是Connection: close且无长度继续读取直到失败 else if (content_length INT_MAX) { // 继续读取直到recv返回0或错误 continue; } } } buffer[total_received] \0; return total_received; } // 使用示例 void process_http_response_fixed(int sock) { char response_buffer[8192]; int received read_http_response_fixed(sock, response_buffer, sizeof(response_buffer), 30); if (received 0) { printf(收到完整响应: %d 字节\n, received); // 查找body开始位置 char* body_start strstr(response_buffer, \r\n\r\n); if (body_start) { body_start 4; // 跳过\r\n\r\n printf(响应体: %s\n, body_start); } } else { printf(接收响应失败或超时\n); } }