有没有人可以一步一步地解释我的android客户端与我的示例中运行PHP的服务器之间的交互?


Can anyone explain, step by step, the interaction between my android client, and the server running PHP in my example?

<?php
$json = $_SERVER['HTTP_JSON'];
echo "JSON: 'n";
echo "---------------'n";
var_dump($json);
echo "'n'n";
$data = json_decode($json);
echo "Array: 'n";
var_dump($data);
echo "'n'n";
$username = $data->username;
echo "Result: 'n";
echo "---------------'n";
echo "username : ", $username, "'n";
?>


public String postJSON() throws JSONException{
    HttpClient httpclient = new DefaultHttpClient();
    HttpPost httppost = new HttpPost(ec2Url + "testjson.php");
    JSONObject json = new JSONObject();
    try {
        json.put("username", "Michael");
        JSONArray postjson = new JSONArray();
        postjson.put(json);
        httppost.setHeader("json", json.toString());
        Log.d(DEBUG_TAG, "toString() " + json.toString());
        httppost.getParams().setParameter("jsonpost", postjson);
        HttpResponse response = httpclient.execute(httppost);
        if(response != null) {
            InputStream is = response.getEntity().getContent();
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            StringBuilder sb = new StringBuilder();
            String line = null;
            try {
                while((line = reader.readLine()) != null) {
                    sb.append(line + "'n");
                }
            } catch(IOException e){
            }
            text = sb.toString();
        }
    return text;} 
    catch (ClientProtocolException e) {
    } catch(IOException e){
    }
    return "BROKE";
}

代码工作,但我不完全理解它。谁能解释一下httppost。setHeader("json", json. tostring())正在做,以及$_SERVER['HTTP_JSON']如何设置等于json. tostring () ?还有,httppost.getParams()。setParameter("jsonpost", postjson)做?它似乎配对在一起"jsonpost"和JSON数组本身,但在PHP的哪里得到接收和它在哪里得到解释?

我过去问过一些不好的问题,所以如果这不是"主题"或不清楚,请不要犹豫告诉我,我会修改它。

实际上,这段代码有点奇怪,它不是一个良好实践的例子,但幸运的是,考虑其中涉及的概念是很好的。

要理解它,需要对HTTP进行介绍。但为了让思考不那么痛苦,我会尽量简化。客户端(Android应用程序)和服务器(运行在HTTP服务器上的PHP)发送字符串(更准确地说是文本数据流)给对方,每次一个。这些字符串被称为HTTP消息。

HTTP消息总是有一个初始部分,称为HTTP头。在报头之后,可以(但不是必须)包含HTTP Body。这些部分用两个连续的新行彼此分开。

Android代码正在发送一个特定类型的HTTP消息:POST (HTTP消息实际上不存在,它是一个"抽象概念")。POST可以包含正文,通常也是这样。

你的第一部分问题是关于POST准备,所以让我们从最终结果开始(这里是你的Android代码发送到服务器的POST的近似值):

POST /testjson.php HTTP/1.1
Host: content.of.your.ec2Url.string
User-Agent: Android Http Client User-Agent
Content-Length: 0
json: {"username": "Michael"}
                                     <- new line here, end of headers, no body

第一行定义了消息的类型(POST)、服务器上要访问的资源(/testjson.php)和客户端的HTTP版本(HTTP/1.1)。后面跟着HTTP Headers。标头是一组简单的冒号分隔的密钥对。它们是HTTP处理许多问题的基本要素,这些问题包括客户端和服务器之间的协商能力、缓存控制、权限、定义读取主体的大小、类型和方式。

Android代码的真正非常规之处在于,应用程序数据是在HTTP Header中发送的,而不是在body或HTTP第一行。这不是一个正确的方法,但这是可能的。 httppost。setHeader("json", json. tostring ())是关于:设置一个名为json的头,值为json. tostring ()

所以,有httppost.getParams()。setParameter("jsonpost", postjson),我承认我不确定它的效果。它似乎被滥用了。httppost.getParams()返回一个HttpParams对象,该对象用于更改此处和此处定义的特定于HTTP协议的内容,而不是设置任意应用程序数据。无论如何,这似乎是一个常见的错误。

最后,PHP的东西,但这是简单得多:在PHP上,所有的HTTP头转换在一个$_SERVER[HTTP_NAME_OF_HEADER]变量(大写头键和替换'-'由'_')。这并不是一个有文档记载的特性(事实上,它部分有文档记载),但我在过去十年中一直在使用它而没有注意到它。所以:
$_SERVER['HTTP_HOST'];            // equals to content.of.your.ec2Url.string
$_SERVER['HTTP_USER_AGENT'];      // equals to Android Http Client User-Agent
$_SERVER['HTTP_CONTENT_LENGTH'];  // equals to 0
//and finally
$_SERVER['HTTP_JSON'];            // equals to {"username": "Michael"}