用Android描述一次完整的网络请求过程

19 篇文章 1 订阅

1.前言

从我们在浏览器的地址栏输入http://blog.csdn.net/seu_calvin后回车,到我们看到该博客的主页,这中间经历了什么呢?简单地回答这个问题,大概是经历了域名解析、TCP的三次握手、建立TCP连接后发起 HTTP请求、服务器响应HTTP请求、浏览器解析html代码,同时请求html代码中的资源(如js、css、图 片等)、最后浏览器对页面进行渲染并呈现给用户。下面分别介绍一下每个过程。

2.域名解析

以Chrome浏览器为例,Chrome会解析域名对应的IP地址。

(1)Chrome浏览器会首先搜索浏览器自身的DNS缓存(可以使用 chrome://net-internals/#dns 来进 行查看),浏览器自身的DNS缓存有效期比较短,且容纳有限,大概是1000条。如果自身的缓存中存在 blog.csdn.net 对应的IP地址并且没有过期,则解析成功。

(2)如果(1)中未找到,那么Chrome会搜索操作系统自身的DNS缓存(可以在命令行下使用 ipconfig /displaydns 查看)。如果找到且没有过期则成功。

(3)如果(2)中未找到,那么尝试读取位于C:\Windows\System32\drivers\etc下的hosts文件,如果 找到对应的IP地址则解析成功。

(4)如果(3)中未找到,浏览器首先会找TCP/IP参数中设置的本地DNS服务器,并请求LDNS服务器 来解析这个域名,这台服务器一般在你的城市的某个角落,距离你不会很远,并且这台服务器的性能都 很好,一般都会缓存域名解析结果,大约80%的域名解析到这里就完成了。否则本地DNS服务器会请求 根DNS服务器。

(5)本地DNS会把请求发至13台根DNS,根DNS服务器会返回所查询域的主域名服务器的地址(.net), 本地DNS服务器使用该IP信息联系负责.net域的这台服务器。这台负责.net域的服务器收到请求后,会返 回.net域的下一级DNS服务器地址(blog.csdn.net)给本地DNS服务器。以此类推,直至找到。

3.HTTP网络请求方法

Http的请求方法代表了客户端想对服务器进行的操作,比如: POSTGET、HEAD、PUT、DELETE、 TRACE、OPTIONS 。 常用的不过于CRUD四个。 增:PUT;删:DELETE;改: POST;查: GET。

2.1Get、Post

2.1.1Get

1.向服务器请求数据,获取资源,在大部分网络请求中,GET方法非常常见,并且它具有幂等性。

2.GET请求没有请求体,对于GET请求的请求参数在URL后面加上一个"?"的后面,参数以 key=value 的形式。参数与参数之间使用"&"进行连接。

3.GET请求是通过 URL 传输参数的,所以GET请求可以传输的参数是有限的。

2.1.2Post

1.用于向表单提交数据,传送的数据放在请求体中。

2.在POST请求中,请求参数放在请求体中,服务器会根据POST请求体中的参数创建一个页面,然后 返回给客户端。POST不具有幂等性。

2.2Get与Post的区别

1. 作用不同:GET 用于获取资源,而 POST 用于传输实体主体。

2. 参数位置不一样:GET 和 POST 的请求都能使用额外的参数,但是 GET 的参数是以查询字符串出 现在 URL 中,而 POST 的参数存储在实体主体中。但是并不是 POST 参数存储在实体主体中就认 为它的安全性更高,我们可以通过一些抓包工具如(Fiddler)查看。 在URL 只支持 ASCII 码,因此 GET 的参数中如果存在中文等字符就需要先进行编码。例如 中文 会 转换为 %E4%B8%AD%E6%96%87 ,而空格会转换为 %20 。POST 支持标准字符集。

3. 安全性:安全的 HTTP 方法不会改变服务器状态,也就是说它只是可读的。 GET 方法是安全的, 而 POST 却不是,因为 POST 的目的是传送实体主体内容,这个内容可能是用户上传的表单数据, 上传成功之后,服务器可能把这个数据存储到数据库中,因此状态也就发生了改变。

4. 可缓存性:GET可以缓存,但是POST大部分情况下无法缓存。 如果要对响应进行缓存,需要满足 几个条件: 请求报文的 HTTP 方法本身是可缓存的,包括 GET 和 HEAD,但是 PUT 和 DELETE 不可缓存, POST 在多数情况下不可缓存的。 响应报文的状态码是可缓存的,包括: 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, and 501。 响应报文的 Cache-Control 首部字段没有指定不进行缓存。 1. 在使用 XMLHttpRequest 的 POST 方法时,浏览器会先发送 Header 再发送 Data。但并不是所有 浏览器会这么做,例如火狐就不会。而 GET 方法 Header 和 Data 会一起发送。 XMLHttpRequest 简介:XMLHttpRequest 是一个 API,它为客户端提供了在客户端和服务器之间 传输数据的功能。它提供了一个通过 URL 来获取数据的简单方式,并且不会使整个页面刷新。这 使得网页只更新一部分页面而不会打扰到用户,局部刷新避免资源浪费。并且XMLHttpRequest 在 AJAX 中被大量使用。

3.Http——HttpURLConnection详解

3.1Android设置网络权限

在AndroidManifest.xml中添加

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

3.2HttpURLConnection简介

在JDK的 java.net 包中已经提供了访问HTTP协议的基本功能的类:HttpURLConnection。 HttpURLConnection是Java的标准类,它继承自URLConnection,可用于向指定网站发送GET请求、 POST请求。

它在URLConnection的基础上提供了如下便捷的方法:

int getResponseCode(); // 获取服务器的响应代码。
String getResponseMessage(); // 获取服务器的响应消息。
String getResponseMethod(); // 获取发送请求的方法。
void setRequestMethod(String method); // 设置发送请求的方法。

3.3HttpURLConnection使用

使用GET方式访问HTTP:

话不多说,直接上代码:

public class MainActivity extends AppCompatActivity {
    private TextView tv_text;
    private Button btn_get;
    String result = "";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_text = findViewById(R.id.tv_text);
        test();
        btn_get = findViewById(R.id.btn_get);
        btn_get.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        //获取要访问的URL
                        try {
                            URL url = new URL("https://api.vvhan.com/api/love?type=json");
                            //获取访问对象
                            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                            //设置请求参数
                            connection.setDoOutput(false);
                            connection.setDoInput(true);
                            //设置请求方式
                            connection.setRequestMethod("GET");
                            //设置缓存
                            connection.setUseCaches(true);
                            //设置重定向
                            connection.setInstanceFollowRedirects(true);
                            //设置超时时间
                            connection.setConnectTimeout(4000);
                            //连接
                            connection.connect();
                            //获取响应码
                            int code = connection.getResponseCode();
                            if (code == 200) {
                                BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                                result = br.readLine();
                            }
                            handler.sendEmptyMessage(0x111);
                        } catch (MalformedURLException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        });

    }

    private void test() {
        String result = "[{\"success\":true,\"id\":400,\"ishan\":\"你的侧脸应该制定为国家一级宝物。\"} \n," +
                "{\"success\":true,\"id\":300,\"ishan\":\"你的侧脸应该制定为国家一级宝物。\"} \n," +
                "{\"success\":true,\"id\":200,\"ishan\":\"你的侧脸应该制定为国家一级宝物。\"} \n]";

        try {
           JSONArray array = new JSONArray(result);
            for (int i = 0; i < array.length(); i++) {
                try {
                    JSONObject jsonObject = array.getJSONObject(i);
                    boolean success = jsonObject.getBoolean("success");
                    int id = jsonObject.getInt("id");
                    String s = jsonObject.getString("ishan");
                    Log.i("array","success:"+success+",id:"+id+",ishan:"+s);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

    }

    Handler handler = new Handler(Looper.getMainLooper()){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if (msg.what==0x111) {
                JSONObject object = null;
                try {
                    object = new JSONObject(result);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                try {
                    boolean success = object.getBoolean("success");
                    int id = object.getInt("id");
                    String s = object.getString("ishan");
                    tv_text.setText(s);
                } catch (JSONException e) {
                    e.printStackTrace();
                }


            }
        }
    };


}

3.4关闭HttpURLConnection

本身要 HttpURLConnection 是很简单的,调用 connection.disconnect() 就可以了。

4.JSON

4.1JSON是什么

Json(Javascript Object notation)作为一种轻量级的数据传输格式,在现代软件开发中广泛使用,采用完 全独立于语言的文本格式,具有可读性强、编写容易,更利于机器的解析与生成。

4.1 JSON与Xml的比较

Json与xml分别作为轻量级的数据传输格式,在软件开发中有着很重要的作用,同时两者在不同的编程 语言中能够很容易的解析与生成。根据自身的优缺点,在实际项目的开发中,选择合适的数据传输格式 尤为重要,比较如下:

1.Json与xml具有极为丰富的解析方式

2.Json与xml比较,json的数据小

3.Json与xml比较,xml能够更好的描述对象

4.Json与xml比较,json的传输效率更高

5.Json与xml比较,在编写方面,xml具有丰富的工具编写

4.2JSON的结构

对象(JSONObject):

对象是一个无序的“‘名称/值’对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个 “:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。

数组(JSONArray):

数组是值(value)的有序集合。一个数组以“[”(左中括号)开始,“]”(右中括号)结束。值之间使用“,”(逗号)分 隔。

4.3JSON的使用:

举个例子来说明:

从网络端获取新闻,并将新闻放入

1.第一步:在activity_main.xml中添加RecycleView

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity3">
<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/rv_show"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
</LinearLayout>

2.第二步:创建子布局 news_item.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="200dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:cardElevation="5dp"
app:cardCornerRadius="5dp">
<RelativeLayout
    android:padding="5dp"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:id="@+id/news_img"
        android:layout_width="190dp"
        android:layout_height="190dp"
        android:scaleType="fitXY"
        app:srcCompat="@drawable/ic_launcher_background" />
    <TextView
        android:layout_toRightOf="@id/news_img"
        android:layout_marginStart="20dp"
        android:textSize="16sp"
        android:id="@+id/news_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
    android:text="TextView" />
    <TextView
        android:id="@+id/news_desc"
        android:layout_marginTop="50dp"
        android:layout_below="@id/news_title"
        android:layout_alignStart="@id/news_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView" />
</RelativeLayout>
</androidx.cardview.widget.CardView>

3.第三步:创建实体类 News.java

public class News {
    private String title;
    private String desc;
    private String pic;
    public News(String title, String desc, String pic){
        this.title = title;
        this.desc = desc;
        this.pic = pic;
    }
    public String getTitle() {
        return title;
    }
    public String getDesc() {
        return desc;
    }
    public String getPic() {
        return pic;
    }
    @Override
    public String toString() {
        return "News{" +
                "title='" + title + '\'' +
                ", desc='" + desc + '\'' +
                ", pic='" + pic + '\'' +
                '}';
    }
}

4.第四步:创建适配器 NewsAdapter.java

package com.hopu.network.adapter;
        import android.util.Log;
        import android.view.LayoutInflater;
        import android.view.View;
        import android.view.ViewGroup;
        import android.widget.ImageView;
        import android.widget.TextView;
        import android.widget.Toast;
        import androidx.annotation.NonNull;
        import androidx.recyclerview.widget.RecyclerView;
        import com.bumptech.glide.Glide;
        import com.hopu.network.R;
        import com.hopu.network.model.News;
        import java.util.List;
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder> {
    private List<News> list;
    public NewsAdapter(List<News> list){
        this.list = list;
    }
    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int
            viewType) {
        View view =
                LayoutInflater.from(parent.getContext()).inflate(R.layout.news_item, parent,
                        false);
        ViewHolder viewHolder = new ViewHolder(view);
        return viewHolder;
    }
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        News news = list.get(position);
        Log.i("适配器",news.toString());
        holder.news_title.setText(news.getTitle());
        holder.news_desc.setText(news.getDesc());
        Glide.with(holder.view).load(news.getPic()).into(holder.news_img);
    }
    @Override
    public int getItemCount() {
        return list.size();
    }
    public class ViewHolder extends RecyclerView.ViewHolder{
        
        ImageView news_img;
        TextView news_title, news_desc;
        View view;
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            this.view = itemView;
            news_img = itemView.findViewById(R.id.news_img);
            news_title = itemView.findViewById(R.id.news_title);
            news_desc = itemView.findViewById(R.id.news_desc);
        }
    }
}

5.第五步:声明RecycleView

public class MainActivity3 extends AppCompatActivity {
    private RecyclerView rv_show;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);
        rv_show = findViewById(R.id.rv_show);
    }
}

6.开始网络编程

public class MainActivity3 extends AppCompatActivity {
    private RecyclerView rv_show;
    private List<News> list = new ArrayList<>();
    private String result;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);
        initDate();
        rv_show = findViewById(R.id.rv_show);
    }
    private void initDate() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                result = NetWorkUtils.doGet("https://api.vvhan.com/api/hotlist?
                        type=36Ke");
                        Log.i("GET请求",result);
                handler.sendEmptyMessage(0x111);
            }
        }).start();
    }
}

7.第七步:传递数据,数据解析

public class MainActivity3 extends AppCompatActivity {
    private RecyclerView rv_show;
    private List<News> list = new ArrayList<>();
    private String result;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);
        initDate();
        rv_show = findViewById(R.id.rv_show);
    }
    private void initDate() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                result = NetWorkUtils.doGet("https://api.vvhan.com/api/hotlist?
                        type=36Ke");
                        Log.i("GET请求",result);
                handler.sendEmptyMessage(0x111);
            }
            
        }).start();
    }
    private Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
//list.clear();
            if (msg.what == 0x111) {
                try {
                    JSONObject object = new JSONObject(result);
                    JSONArray array = object.getJSONArray("data");
                    for (int i = 0;i<array.length();i++) {
                        JSONObject object1 = array.getJSONObject(i);
                        String title = object1.getString("title");
                        String desc = object1.getString("desc");
                        String pic = object1.getString("pic");
                        News news = new News(title, desc, pic);
                        Log.i("JSON解析",news.toString());
                        list.add(news);
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }
    };
}

8.第八步:当数据完毕后,给RecycleView设置适配器

public class MainActivity3 extends AppCompatActivity {
    private RecyclerView rv_show;
    private List<News> list = new ArrayList<>();
    private String result;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);
        initDate();
        rv_show = findViewById(R.id.rv_show);
    }
    private void initDate() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                result = NetWorkUtils.doGet("https://api.vvhan.com/api/hotlist?
                        type=36Ke");
                        Log.i("GET请求",result);
                handler.sendEmptyMessage(0x111);
            }
        }).start();
    }
    private Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
//list.clear();
            if (msg.what == 0x111) {
                try {
                    JSONObject object = new JSONObject(result);
                    JSONArray array = object.getJSONArray("data");
                    for (int i = 0;i<array.length();i++) {
                        JSONObject object1 = array.getJSONObject(i);
                        String title = object1.getString("title");
                        String desc = object1.getString("desc");
                        String pic = object1.getString("pic");
                        News news = new News(title, desc, pic);
                        Log.i("JSON解析",news.toString());
                        list.add(news);
                    }
                    NewsAdapter newsAdapter = new NewsAdapter(list);
                    LinearLayoutManager layoutManager = new
                            LinearLayoutManager(MainActivity3.this);
                    rv_show.setLayoutManager(layoutManager);
                    rv_show.setAdapter(newsAdapter);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }
    };
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值