java.net.ProtocolException: Unexpected status line: 关于Java/Android http post json的发送接收

1.简要
在很多项目中会用到关于http POST/GET 的需求,而且一般数据格式都是json格式一般的过程都是 client——>server——>client 
就是 客户端给服务端发送post/get请求,服务端接收到请求后,再将响应数据返回给client。这就是一个完整的http post/get过程


http请求是通过一种短连接的形式让客户端和服务端进行数据通信的方式,其实它是一种基于TCP协议的应用层协议,用http client和server建立通信完成一波数据交互后,连接会自动断开,下次必须重新建立连接。
简单介绍到这里,更多关于http协议的信息可以在网上有很多介绍)


GET 方法的表单发送的信息,对任何人都是可见的(会显示在浏览器的地址栏),并且对发送信息的量也有限制。
 POST 方法的表单发送的信息,对任何人都是不可见的(不会显示在浏览器的地址栏),并且对发送信息的量也没有限制
 (对于post和get更多信息网上有很多介绍)


2.用java进行http post/get


下面用一个java语言写的http post json数据为例子,直接上代码:


public static String httpPost(String strURL, String params) {//参数1:url接口地址 参数2:json数据(已经转换成string型)
		System.out.println(strURL);
		System.out.println(params);
		try {
			URL url = new URL(strURL);// 创建连接
			HttpURLConnection connection = (HttpURLConnection) url
					.openConnection();
			connection.setDoOutput(true);
			connection.setDoInput(true);
			connection.setUseCaches(false);
			connection.setInstanceFollowRedirects(true);
			connection.setRequestMethod("POST"); // 设置请求方式
			connection.setRequestProperty("Accept", "application/json"); // 设置接收数据的格式
			connection.setRequestProperty("Content-Type", "application/json"); // 设置发送数据的格式
			connection.connect();
			OutputStreamWriter out = new OutputStreamWriter(
					connection.getOutputStream(), "UTF-8"); // utf-8编码
			out.append(params);
			out.flush();
			out.close();
			// 读取响应
			int length = (int) connection.getContentLength();// 获取长度 -1便是错误
			InputStream is = connection.getInputStream();
			if (length != -1) {
				
				  byte[] bytes = new byte[length];
				  int readCount = 0; // 已经成功读取的字节的个数
				  while (readCount < length) {
				   readCount += is.read(bytes, readCount, length - readCount);
				  }

				String result = new String(bytes, "UTF-8"); // utf-8编码
				System.out.println("result=" + result);
				return result;
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return "error"; // 自定义错误信息
	}

对于上面的参数2,是需要发送的数据,当然可以这样写

JSONObject jsonParam = new JSONObject();  
                jsonParam.put("chnl_id", "11");// 红谷滩新闻资讯,channelId 77  
                jsonParam.put("title", bean.getTitle());// 标题  
                jsonParam.put("content", bean.getContent());// 资讯内容  
                jsonParam.put("source_url", bean.getSourceUrl());// 资讯源地址  
                jsonParam.put("source_name", bean.getSourceFrom());// 来源网站名称  
                jsonParam.put("img_urls", bean.getImgUrls());// 采用 url,url,url 的格式进行图片的返回  
得到的jsonParam.toString就可以直接得到该参数

一般都可以采用上述方法来实现post,感觉没一点问题一样

同事发现这种方法在Android上是有问题的,总是第一次请求可以得到数据,第二次请求不行,第三次又可以,第四次又不行。。。。。。


看了下log是这样的

System.err(16168): java.net.ProtocolException: Unexpected status line: 
System.err(16168): at com.android.okhttp.internal.http.RawHeaders.setStatusLine(RawHeaders.java:108)
System.err(16168): at com.android.okhttp.internal.http.RawHeaders.fromBytes(RawHeaders.java:308)

。。。。。。。。。。。


分析原因,每次到read的时候就会出现上述的间隔失败的情况,如果不使用read,整个通信过程完全正常,就连介绍到的数据长度也是正常,所以我们判断可能是read的原因;

但是InputStream好像就只有三种read方式,三种试过了都没有进展,就连BufferReader+InputStream也试过了,还是有上面的问题。

查了很多信息,有的说是发送的数据格式有问题,但是我发送的同样的数据用java工程就可以,用Android就出现上面问题;再有的就说是Android4.4不能用上面的API(或许靠谱),于是就查找新的API,但是为什么上面API在Android里,用read的时候有问题,现在还没有搞清楚,有大神看到可以指导下


3.Android Http POST

上面2 中遇到了问题,所以就查找其他API来解决问题

这里用到了DefaultHttpClient和HttpPost

上代码:

public static void httpPostWithJson(String url, String json)
			throws Exception {
		// 将JSON进行UTF-8编码,以便传输中文
		String encoderJson = URLEncoder.encode(json, HTTP.UTF_8);

		DefaultHttpClient httpClient = new DefaultHttpClient();
		HttpPost httpPost = new HttpPost(url);
		httpPost.addHeader(HTTP.CONTENT_TYPE, "application/json");
		
		 StringEntity se = new StringEntity(json,"utf-8");//解决中文乱码问题 
		se.setContentType("text/json");
		se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,
				"application/json"));
		httpPost.setEntity(se);
		HttpResponse response = null;

		response = httpClient.execute(httpPost);
		if (response.getStatusLine().getStatusCode() == 200) {
			try {
				/** 读取服务器返回过来的json字符串数据 **/
				String strResult = EntityUtils.toString(response.getEntity());
				Log.d("zph", "strResult=" + strResult);
			} catch (IllegalStateException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

	}
其中参数1和2跟上面的2中的参数是一样的

用上面的方法就可以完美解决异常:

java.net.ProtocolException: Unexpected status line: 

转载请注明出处

http://blog.csdn.net/pishum/article/details/51009278

2016-03-29

Pishum




你可能感兴趣的:(java,android)