Android http post中文乱码问题的修正

本文讨论了在使用DefaultHttpClient进行Android平台的Post请求时,如何正确处理UTF-8编码的数据以避免服务器接收出现乱码的问题。通过实例演示了使用StringEntity构造Post请求体并指定编码方式的有效方法。
出现了类似问题,网上找的答案,记录一下~~

在使用DefaultHttpClient向服务器发送post请求,在请求体中
发送utf-8编码的数据。
android默认编码是utf-8,所以从EditText获取的text即为utf-8编码的数据。
但是服务器接受就是乱码。
//reqEntity.setContentEncoding("UTF-8");也是乱码。
但是StringEntity reqEntity = new StringEntity(post, HTTP.UTF_8);在构造
中指定则没有问题了。
<think> 我们注意到用户的问题是关于在Android Service中传入参数时出现一个特定的错误: 'Invalid character found in method name [0x160x030x030x010xa70x010x000x010xa30x030x030xbe0xae0xa70x19n0xb90xf60xa20xe4c0xba0xcd0x860xbc%0xfe0xe50xb8.0xcb0xa00xb20x91V0x7fh0xd929m~R ]. HTTP method names must be tokens' 首先,这个错误信息看起来像是HTTP协议相关的错误,而不是直接与Service参数传递相关。错误信息指出在HTTP方法名中发现了无效字符,要求方法名必须是有效的令牌(tokens)。这通常发生在尝试使用HTTPS的端口进行HTTP通信,或者SSL/TLS握手失败时。 但是,用户提到是在“service里传入参数时”出现该错误。我们需要结合上下文分析: 1. 用户之前的问题是关于在Android Service中传入参数的方法,我们给出了详细的回答。 2. 现在用户遇到了这个错误,可能是在使用HTTP请求(比如在Service中发起网络请求)时传入参数导致的。 因此,我们推断:用户可能在Service内部使用了网络请求(如HTTP请求)来传递参数到服务器,而在构建HTTP请求时出现了问题。 错误原因分析: 错误信息中的一串十六进制(0x16, 0x03等)看起来像是TLS握手的开头(0x16表示握手记录,0x0301或0x0303表示TLS版本)。这通常意味着: - 客户端尝试使用HTTP协议连接一个HTTPS的端口(比如443端口),导致服务器返回的是TLS握手数据,而客户端却试图解析为HTTP响应。 - 或者,客户端使用了HTTPS,但在SSL握手过程中出现了问题,导致接收到的数据不符合HTTP协议。 解决方案: 步骤1:检查URL协议 确保你使用的URL是https://(需要加密连接)还是http://(普通连接)。如果服务器要求HTTPS,而你使用了HTTP,则可能会重定向,但这里的情况更可能是你试图用HTTP客户端解析SSL握手数据。 步骤2:检查端口 如果指定了端口,确保端口正确。通常,HTTP默认80端口,HTTPS默认443端口。 步骤3:检查网络库 如果你使用了第三方网络库(如OkHttpHttpURLConnection等),确保正确配置了HTTPS。例如,如果服务器使用自签名证书,可能需要设置信任所有证书(仅用于测试环境)或添加正确的证书。 步骤4:调试网络请求 可以尝试使用工具(如Postman)测试相同的请求,以确定是服务器问题还是客户端问题。 步骤5:检查Service中的网络请求代码 在Service中发起网络请求的代码,检查是否在URL、请求方法(GET、POST等)或请求头中传入了非法字符。特别是,确保请求方法(如“GET”、“POST”)是有效的HTTP方法名。 错误日志中显示的乱码其实是TLS握手的数据,被错误地当作HTTP响应来解析,因此报错说在方法名中发现了无效字符(因为HTTP响应的第一行应该是“HTTP/1.1 200 OK”这样的,而这里却是二进制数据)。 示例修正: 假设你在Service中使用HttpURLConnection: ```java URL url = new URL("http://example.com/api"); // 注意:如果服务器要求HTTPS,这里必须用https HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); // 这里的方法名必须是有效的,如GET, POST等 ``` 如果服务器使用HTTPS,则应该使用https URL,并且可能需要处理证书问题。 另外,如果你在Service中使用了Intent传递参数来启动一个网络请求,确保参数中不包含破坏HTTP请求的非法字符。但根据错误信息,问题更可能出在协议或端口上。 总结:这个错误通常是由于错误地使用HTTP连接了HTTPS端口,或者在SSL/TLS握手失败后尝试解析数据为HTTP响应造成的。请检查你的URL协议和端口,并确保正确配置了HTTPS。 如果问题仍然存在,请提供更多代码细节以便进一步排查。 §§相关问题§§ 1. 如何在 Android Service 中正确发起 HTTPS 请求? 2. 处理自签名证书的 HTTPS 请求的方法有哪些? 3. 如何避免在网络请求中出现协议错误? 4. 在 Service 中使用 Retrofit 发起网络请求的步骤是什么? 5. 如何捕获和分析 Android 网络请求中的异常? </think> ### 解决 `Invalid character found in method name` 错误的方法 您在 Service 中传入参数时遇到的错误: ``` Invalid character found in method name [0x160x030x030x010xa70x010x000x010xa30x030x030xbe0xae0xa70x19n0xb90xf60xa20xe4c0xba0xcd0x860xbc%0xfe0xe50xb8.0xcb0xa00xb20x91V0x7fh0xd929m~R ]. HTTP method names must be tokens ``` **根本原因**:该错误表明您的 HTTP 请求头中包含非法字符(如二进制数据),通常是: 1. 意外发送了 HTTPS 流量到 HTTP 端口 2. 请求头被二进制数据污染 3. 使用了无效的 URL 或协议 #### 解决方案步骤: 1. **检查 URL 协议一致性** ```java // 错误:混合协议(HTTP请求发送到HTTPS端口) String url = "http://api.example.com:443/data"; // 443是HTTPS端口 // 正确:协议和端口匹配 String url = "https://api.example.com:443/data"; // HTTPS协议 + 443端口 ``` 确保端口号与协议匹配: - HTTP → 80端口 - HTTPS → 443端口[^1] 2. **清理请求头参数** ```java // 移除参数中的非ASCII字符 String cleanParam = parameter.replaceAll("[^\\x20-\\x7E]", ""); // 或使用URL编码 String encodedParam = URLEncoder.encode(rawParam, "UTF-8"); ``` 特别检查: - 空格、中文等特殊字符 - 不可打印的控制字符 - JSON/XML数据中的非法转义符 3. **验证HTTP方法名** ```java // 仅允许标准HTTP方法 if (!Arrays.asList("GET", "POST", "PUT", "DELETE").contains(method)) { throw new IllegalArgumentException("无效的HTTP方法"); } ``` 4. **使用调试工具捕获原始请求** ```bash # 通过tcpdump抓包分析 adb shell tcpdump -s0 -w /sdcard/capture.pcap ``` 使用Wireshark分析捕获的包,检查: - 请求头的二进制数据 - 协议是否被意外加密 5. **更新网络库版本** 在 `build.gradle` 中: ```gradle dependencies { // 修复旧版本okhttp的协议处理缺陷 implementation 'com.squareup.okhttp3:okhttp:4.10.0' } ``` #### 完整示例(OkHttp) ```java // Service中使用安全的参数传递 public class MyService extends Service { void sendData(String param) { OkHttpClient client = new OkHttpClient(); // 1. 清理和编码参数 String cleanParam = URLEncoder.encode(param, "UTF-8"); // 2. 构建合法URL HttpUrl url = new HttpUrl.Builder() .scheme("https") // 强制使用HTTPS .host("api.example.com") .addPathSegment("endpoint") .addQueryParameter("data", cleanParam) .build(); // 3. 发送请求 Request request = new Request.Builder() .url(url) .method("POST", RequestBody.create("", null)) // 明确指定方法 .build(); client.newCall(request).enqueue(...); } } ``` #### 关键预防措施 1. **协议强制**:始终显式指定 `https://` 避免协议推断 2. **参数消毒**:使用 `java.net.URLEncoder` 处理所有动态参数 3. **端口审查**:避免自定义端口,除非服务端明确要求 4. **二进制检测**:添加参数验证逻辑: ```java if (param.matches(".*[^\\x20-\\x7E].*")) { // 拒绝包含非ASCII字符的参数 } ``` > 该错误通常发生在HTTP请求头被TLS握手数据污染时(如HTTP请求误发到HTTPS端口),通过上述方法可解决90%的类似问题[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值