现在的位置: 首页 > 综合 > 正文

httpClient 4.X与PHP服务器通信详解

2017年11月20日 ⁄ 综合 ⁄ 共 7294字 ⁄ 字号 评论关闭

前言:近期搞android开发,初接触JAVA,对其了解还不够深入,但遇到通信问题时,因为我以为搞过PHP,对PHP还是比较了解的,所以决定用PHP来写后台,但网络上有关客户端与PHP服务器的例子真是少之又少,只能自己一步步尝试,还好难度不大,用了一天的时间解决了服务器通信问题,分享给大家。

一、前期准备

1、将自己电脑配置成PHP服务器,(我电脑的IP是:222.195.151.19),这个东东我就不教了,如果不懂得怎么配PHP服务器的话,我劝你还是别用PHP做后台了。

2、用一台真机(PAD)通过WIFI连接局域网路由,这样就使服务器(也就是我的电脑)和PAD处于同一个局域网了。稍微对路由器和NAT转换有些了解的人应该知道为什么处在同一个局域网的两个主机是可以通信的,而不在同一局域网,不可能通信的。这里只需要知道必须处于同一个局域网就可以了,如果想深究,百度下《NAT转换知识详解》;

二、安装httpClient

1、下载

http://hc.apache.org/downloads.cgi下载HttpClient 4.3.1(目前最新版),解压后,可以看到几个jar包:

2、导入到工程

  • 1、所需包:这些包我们并用不完,我的博客里只用到这两个包:httpclient-4.3.1.jar、httpcore-4.3.jar;
  • 2、加入工程:在工程中应该会有一个libs文件夹,如果没有新建一个,并将这两个包拷贝到里面去;
  • 3、加入path:每个包上右击,选择->BuidPath->Add to Path,这样,就导入到工程中了

3、配置AndroidManifest.xml

在AndroidManifest.xml的</manifest>标签前添加如下代码:

<!-- 连接互联网权限 -->

<uses-permission android:name="android.permission.INTERNET"></uses-permission> 

三、GET方法通信

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		// 创建默认的httpClient实例.
		HttpClient httpclient = new DefaultHttpClient();
		try {
			// 创建httpget.访问本地服务器网址
			HttpGet httpget = new HttpGet(
					"http://222.195.151.19/index.html");
			Log.v("msg", "executing request " + httpget.getURI());
			// 执行get请求.
			HttpResponse response = httpclient.execute(httpget);
			// 获取响应实体
			HttpEntity entity = response.getEntity();
			Log.v("msg", "--------------------------------------");
			// 打印响应状态
			Log.v("msg", "" + response.getStatusLine());
			if (entity != null) {
				// 打印响应内容长度
				Log.v("msg",
						"Response content length: " + entity.getContentLength());
				// 打印响应内容
				Log.v("msg",
						"Response content: " + EntityUtils.toString(entity));
			}
			Log.v("msg", "------------------------------------");

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			// 关闭连接,释放资源
			httpclient.getConnectionManager().shutdown();
		}
	}

}

这段代码是获取htdocs目录下的index.html的网页内容;

查看LogCat,添加一个filter,将标识为"msg"的消息过滤出来,结果如下:(下面还有很多,我只截了一部分)


                                                    源码在文章最后(包括前后台工程文件)

四、POST方法之一:简单实现通信

废话不多说,直接上代码:

android端:

基本流程是这样:

1、构造HttpClient实例,DefaultHttpClient httpclient = new DefaultHttpClient(); 

2、构造要POST过去的参值对:

        	 // 创建httpost.访问本地服务器网址  
        	 HttpPost httpost = new HttpPost("http://222.195.151.19/try_an_server/index.php");  
            
        	 //构造POST方法的{name:value} 参数对
        	 List <NameValuePair>  vps = new ArrayList <NameValuePair>();   
             //将参数传入post方法中
             vps.add(new BasicNameValuePair("action", "insert"));  
             vps.add(new BasicNameValuePair("name", "进去了"));
             //   BasicNameValuePair("name", "value"), name是post方法里的属性, value是传入的参数值

3、POST过去:

httpost.setEntity(new UrlEncodedFormEntity(vps, HTTP.UTF_8));
response = httpclient.execute(httpost);  //执行

4、取出返回的信息并操作

			entity = response.getEntity(); //取出返回的信息
			
            Log.v("msg","----------------------------------------");
            Log.v("msg",""+response.getStatusLine());                           //服务器返回状态
            Header[] headers = response.getAllHeaders();                    //返回的HTTP头信息
            for (int i=0; i<headers.length; i++) {                              
            	Log.v("msg",""+headers[i]);
            }
            Log.v("msg","----------------------------------------");
            String responseString = null;
            if (response.getEntity() != null) {
            responseString = EntityUtils.toString(response.getEntity());      //返回服务器响应的HTML代码
            Log.v("msg",responseString);                                   //打印出服务器响应的HTML代码
           

完整代码如下:

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		//创建默认的httpClient实例.  
		DefaultHttpClient httpclient = new DefaultHttpClient(); 
        HttpResponse response = null;
        HttpEntity entity = null;
                                                             
        try{
        	 // 创建httpost.访问本地服务器网址  
        	 HttpPost httpost = new HttpPost("http://222.195.151.19/try_an_server/index.php");  
            
        	 //构造POST方法的{name:value} 参数对
        	 List <NameValuePair>  vps = new ArrayList <NameValuePair>();   
             //将参数传入post方法中
             vps.add(new BasicNameValuePair("action", "insert"));  
             vps.add(new BasicNameValuePair("name", "进去了"));
             //   BasicNameValuePair("name", "value"), name是post方法里的属性, value是传入的参数值
             
        	httpost.setEntity(new UrlEncodedFormEntity(vps, HTTP.UTF_8));
			response = httpclient.execute(httpost);  //执行
			entity = response.getEntity(); //取出返回的信息
			
            Log.v("msg","----------------------------------------");
            Log.v("msg",""+response.getStatusLine());                           //服务器返回状态
            Header[] headers = response.getAllHeaders();                    //返回的HTTP头信息
            for (int i=0; i<headers.length; i++) {                              
            	Log.v("msg",""+headers[i]);
            }
            Log.v("msg","----------------------------------------");
            String responseString = null;
            if (response.getEntity() != null) {
            responseString = EntityUtils.toString(response.getEntity());      //返回服务器响应的HTML代码
            Log.v("msg",responseString);                                   //打印出服务器响应的HTML代码
            }
        } catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				 if (entity != null)
				 {
//					entity.consumeContent();//强制释放资源
					httpclient.getConnectionManager().shutdown();//关闭连接
					//这两种释放连接的方法都可以
				 }
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}                                                   // release connection gracefully
        }
	}

}

解析:

这里往服务端传了两个键值对{action : insert  }  {  name : 进去了}

PHP端代码:
服务端完成的功能比较简单,取出action和name对应的值,如果action是"insert",就将name的值写入到C盘根目录下的try.txt文件中;
代码如下:

<?php
header ( 'Content-type:text/json' ); // 这句是重点,它告诉接收数据的对象此页面输出的是json数据;
/**
 *整个程序的返回值是这样定义的:首先返回的JSON类型数据
 *程序运行正确,id=1;运行出错,id=0;
 *value字段,对应状态码
 */
$action = $_POST ['action'];
$name = $_POST ['name']; // 取出POST过来的值

if ($action == 'insert') {
	$filename = "C:/try.txt";
	if (! file_exists ( $filename )) {
		
		// 如果文件不存在,则创建文件
		@fopen ( $filename, "w" );
		if (is_writable ( $filename )) {
			
			// 打开文件以添加方式即"w"方式打开文件流
			if (! $handle = fopen ( $filename, "w" )) {
				$returnValue = json_encode(array('id' =>'0','value'=>"文件不可打开"));
				echo $returnValue;
				exit ();
			}
			if (! fwrite ( $handle, $name )) {
				$returnValue = json_encode (array(array('id'=>'0','value'=>"文件不可写")));
				echo $returnValue;
				exit ();
			}
			
			// 关闭文件流
			fclose ( $handle );
		}
	}
	
	$returnValue = json_encode(array(
			array('id'=>'1','value'=>"正确"),
			array('id'=>'1','value'=>"尝试多参数代码")));
	echo $returnValue;
	
} else {
	$returnValue = json_encode(array('id'=>'error'));
	echo $returnValue;
}

注意:
这里是以json方式返回的,向客户端返回值用echo 将其输出即可,完全与平时后台编码习惯一致;

android端输出:

 

源码在底部

五、POST方法之二:解析服务端JSON数据

这里PHP端代码不变,在android端,发送POST消息,和获取返回消息的方法都是一样的,不同的只是,在获取到返回的数据后,如何取到保存在其中的name-value值对;下面的代码从得到返回的response数据开始

response = httpclient.execute(httpost);  //执行

if (response.getEntity() != null) {            	
	//如果服务器端JSON没写对,这句是会出异常,是执行不过去的
 BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));  
 String s = reader.readLine();
 for (; s != null; s = reader.readLine()) { 
     builder.append(s);  
 }  
 Log.i("msg","builder.toString = "+ builder.toString()); 
 
 jsonArray = new JSONArray(builder.toString());  
 for (int i = 0; i < jsonArray.length(); ++i) {  
     JSONObject jsonObject = jsonArray.getJSONObject(i);  
     Log.i("msg","id = "+jsonObject.getInt("id") + "");  
     Log.i("msg","name = "+jsonObject.getString("value"));  
 }  
}

这里在得到response结果以后,总共分两步
1、将返回结果组装成JSON字符串;对应代码:

if (response.getEntity() != null) {            	
	//如果服务器端JSON没写对,这句是会出异常,是执行不过去的
 BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));  
 String s = reader.readLine();
 for (; s != null; s = reader.readLine()) { 
     builder.append(s);  
 }  

2、利用JSON字符串生成JSON数组,并操作

 jsonArray = new JSONArray(builder.toString());  
 for (int i = 0; i < jsonArray.length(); ++i) {  
     JSONObject jsonObject = jsonArray.getJSONObject(i);  
     Log.i("msg","id = "+jsonObject.getInt("id") + "");  
     Log.i("msg","name = "+jsonObject.getString("value"));  
 } 

android端返回结果:

源码来啦,所有的实例打包在一起了:http://download.csdn.net/detail/harvic880925/6743797(不要分,仅供分享)

 运行方法:(源码中每个方法都讲了如何运行该实例,具体看源码《此例运行方法.txt》文件)

1 、将android端代码里的222.195.151.19改成自已服务端的IP地址;

 2、将对应有服务器端文件或文件夹放在Apache服务器的htdocs目录下;(PHP工程写于zend studio下)

 六:与simpleAdapter结合起来 (利用服务器返回数据,生成列表)

通过与前面的《List控件使用---SimpleAdapter使用详解(一)》《List控件使用---SimpleAdapter使用详解(二)》结合起来,我们就可以实现通过服务器返回的JSON数据,生成simpleAdapter列表的形式,具体代码我就不讲了,给出源码,大家自己研究下吧,先上效果图:

源码地址:http://download.csdn.net/detail/harvic880925/6744205

 

 请大家尊重原创者的版权,转载请标明出处,谢谢:http://blog.csdn.net/harvic880925/article/details/17416417

 

抱歉!评论已关闭.