基础

如果要相对清楚的明白一次普通的网络请求的流程,首先要明白Http协议的一些基础,接下来的内容基于常用的Http1.1协议

请求URL

这里以普通的Http/Https为例
平常在使用浏览器的时候都会有一个请求资源标识符,比方说http://www.baidu1.com这种,具体的含义就是[scheme]://[host]:[post(默认80,可以隐藏)]/path/...这种。
scheme:请求协议。
在一个完整的通话流程中,为了保证发送数据、接收数据、传输数据等操作的统一性,必须先预先定义一个协议,这个协议内部会预先定义好一系列的规则,接下来的操作会基于这一套规则进行。
host:请求域名。
网络请求实际上就是某一个主机访问另一个主机的过程,那么对于被访问的主机必须要有标识,这个就是域名。
实际的过程中会相对复杂,单纯通过一个域名是无法找到主机的,因为在传输的过程中基本的标识是IP地址,那么中间会需要DNS服务器将域名转换为确切的一个IP地址,接着再通过这个IP地址去访问对应的主机
port:请求端口
当通过某一个IP地址访问到对应主机之后,但是一个主机可能有多个服务,比方说Http和Https这两个不同的协议,同一台主机应该是可以处理这两种不同的协议,那么就是通过不同的端口来进行区分,目前默认的Http是80端口,Https是443端口。
path:当确切访问到主机的某一个端口后,为了区别访问的具体文件,需要通过path来指定具体的访问对象

Http协议

这里以Http1.1协议为例
在一次的通信过程中,传输的基本单位称为报文,这里看一下报文的基本结构,这个也是传递过程中的数据,报文主要关注请求报文和响应报文即可

请求报文

协议中定义的报文有着自己的格式,接下来看一下一个Http1.1的请求报文格式

起始行

请求方式 host/path/...?参数 协议
举例说明:(注意空格)
POST www.hh.com?a=1 HTTP/1.1

请求头部

起始行结束之后要进行换行,然后接着写入请求头部数据,请求头部的基本格式是键值对模式。
需要添加的头部1: 参数1
需要添加的头部2: 参数2
...其余需要添加的头部
换行符
这里以一个常用的头部作为例子说明一下:
Connection: Keep-alive(长连接)
Content-Length: 10248(数据的字节数)
Content-Type: multipart/form-data(表单格式数据)
Host: api.hh.com(请求域名)
换行符

请求数据

这里以form表单为例子,传输一个文本和一个文件,注意空格
--boundary(一串字符)
Content-Disposition: form-data; name="text1"
Content-Length: 5

text1
--boundary(一串字符)
Content-Disposition: form-data; name="file1";
filename="water.png"
Content-Type: application/octet-stream
Content-Length: 该文件的字节数

##########(总之就是该文件的二进制流数据)
--boundary(一串字符)--
这就是定义的表单数据格式,通过分隔符开始,然后通过特定的分隔符结束。接着在获取对应数据的时候只要获得name,然后去读取对应数据即可。

传输模式

数据拼接完成之后,接下来要做的就是将这些数据传输到对应主机(服务器)上面,在Java层面来说,一旦通过socket进行TCP连接之后,将会在发起连接的主机和被连接的主机之间建立一个流通道,那么只需要通过向被连接主机的输出流写入上述报文数据,这样就完成了发送数据请求的流程。

总结

这里简单的模拟一个完整报文用于明确请求报文数据
POST api.bi.com HTTP/1.1
Content-Type: multipart/form-data
Content-Length: 10005
Connection: Keep-alive

--abcdefghijklmn
Content-Disposition: form-data;name="text1"
Content-Length: 5

text1
--abcdefghijklmn
Content-Disposition: form-data;name="file1";filename="water.png"
Content-Type: application/octet-stream
Content-Length: 10000

#########(二进制数据,看上去就是一堆乱码)
--abcdefghijklmn--

响应报文

发送一个请求到服务器之后,服务器进行一些业务上面的处理,接着便是返回结果通知发送请求的主机,以方便主机进行后续操作。
和上面相似的,也是通过报文的格式返回

起始行

协议 状态码 状态码对应说明
举例:
http/1.1 200 OK
表示当前协议为Http1.1,并且请求成功。
Http默认定义了很多状态码,这个可以自行查阅资料,比方说200表示成功、304表示缓存没有变化、404表示请求资源未找到等等

响应头部

以请求一张图片为例子:
Date: Tue, 15 Aug 2017 03:38:02 GMT(服务端处理时间)
Content-Type: image/png
Content-Length: 10005
Expires: Fri, 13 Aug 2027 03:38:02 GMT(响应数据过期时间)
Last-Modified: Fri, 11 Aug 2017 08:55:57 GMT(响应数据在服务端最后一次修改时间)
Location: http://www.ba.com(如果当前返回重定向,则该头部就是用来标记需要重新访问的URL)
Cache-Control: no-cache, no-store, must-revalidate
换行符

响应数据

实际上就是字节流数据,需要更具自身的需求进行处理

传输模式

这里服务端需要往发起请求的主机的输出流中写入数据,从发起请求的主机角度上面来看,就是通过获取服务端的输入流来读取响应数据即可。

Android的一个例子

这里通过HttpURLConnection来实现一个简易的连接

    try {
            //请求URL
            URL url = new URL("http://api.kdniao.cc/Ebusiness/EbusinessOrderHandle.aspx");
            //通过该URL打开一个TCP连接通道
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setReadTimeout(30000);//读取超时
            connection.setConnectTimeout(20000);//连接超时
            connection.addRequestProperty("Connection","Keep-Alive");//添加请求头部
            connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
            connection.setRequestProperty("Accept-Encoding","utf-8");
            connection.setDoOutput(true);
            //进行POST传参
            connection.setRequestMethod("POST");
            OutputStream os = connection.getOutputStream();
            String text = "RequestType=1002&EBusinessID=1";
            os.write(text.getBytes("UTF-8"));
            os.flush();
            os.close();

            //该接口不需要传参
            int code = connection.getResponseCode();//获取状态码
            if(code == 200){//当前请求成功
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                //获取响应流
                BufferedInputStream bufferedInputStream = new BufferedInputStream(connection.getInputStream());
                int num = -1;
                while (-1 != (num = bufferedInputStream.read())){//读取服务端返回的数据
                    outputStream.write(num);
                }
                bufferedInputStream.close();
                Log.i("tag1",outputStream.toString());//打印数据
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

实际上该接口的参数没有传完整,这里只是通过一个例子说明,这个接口要求数据格式为application/x-www-form-urlencoded,这个是要求参数通过a1=123&a2=123这种方式进行传递。如果是上述说过的form-data模式,那么text在拼接的时候处理不同,要手动拼接boundary之类的数据。

总结

这篇文章仅仅希望能够入门网络请求基础,实际在使用的时候,一般不会自己进行数据拼接和获取,毕竟现在现成封装后的库还是很多的,不过基础还是要理解的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,069评论 4 358
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,212评论 1 287
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 105,912评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,424评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,741评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,194评论 1 206
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,553评论 2 307
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,289评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,923评论 1 237
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,251评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,775评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,144评论 2 249
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,698评论 3 228
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,936评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,658评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,214评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,159评论 2 258

推荐阅读更多精彩内容