写给女朋友:理解服务端的工作原理(上) April 5, 2018 [TOC] ### 前言 女票学了一阵前端了,一般来讲,一个牛逼的前端至少会一种服务端语言,一个负责的男票至少给小傻子写一篇服务端入门教程。 本文的主要目的是理解服务端运作的原理,`Cookie`和`Session`的概念,以及如何通过`Token鉴权`。我会从最基础的说起,便于你理解。之所以用`PHP`是因为拍黄片太简单了,理解比较直观,你可以趁机了解以下嘛,之后服务端可以学习以下`express`。 接下来进入正题,以下内容理解即可,不需动手实践,如需了解更多,自行百度啊。 ### 互联网的基础 TCP/IP 协议 简单来说,协议呢就是一种规范,大家都遵守,按照协议的要求去发送/接收数据包就不会出错。TCP协议属于传输层,用于传输数据。IP协议给互联网的每一个联网设备设定了一个地址,这样我给你发信息的时候知道把信息往哪送了。 一般常见问题 TCP/IP协议分几层呀,每层有什么用啊,可以参考百科。 ### Socket 网络套接字 Socket你可以理解对TCP/IP协议的一个封装,他通常由操作系统提供相应的Socket API,用于建立数据连接进行数据传输。Socket主要分为两个部分:`服务端`和`客户端`。服务端负责`监听`,监测有没有客户端连接进来,一旦二者确定连接后,就可以相互发送信息了。这里需要注意的时,是`客户端`主动去连接`服务端`,`服务端`不能主动连接`客户端`。客户端如何主动连接服务端呢?就是知道服务端的地址,也就是`IP地址`啦,同时还需要知道另一个参数:`端口`。 ### Socket 实验 如下图所示,做了个简单的实验平台。左侧是客户端部分,右侧是服务端部分。 ![](/images/2018/04/227276035.png) 实验过程如下: 首先客户端连接服务端,连接后服务端会收到客户端连接信息。 然后,连接成功后,双方可以双向通信了,客户端发送Hi,服务端发送Hello,双方都可以接收到。 实验结果: ![](/images/2018/04/442393238.png) ### HTTP 协议 上面说了半天你可能就纳闷了,这和Web服务端有啥关系呀。其实不难看出,TCP/IP是Web服务端的通信基础。既然能通信了,咱们是不是搞个标准,这样大家做的不同浏览器可以访问相同的服务端,不同的服务端可以被相同的浏览器解析,只要标准一致,就好说。HTTP横空处世,他就是规定了Web数据怎么传,大家按照规定好的来就行。 直观理解: 还是之前的实验平台,我只开启服务端,端口8080,这次我不用Socket客户端去连接服务端了,而是在**浏览器**里输入`http://127.0.0.1:8080`,**注意`:8080`,我输入了端口号**,猜猜实验平台收到了什么数据?看下图: ![](/images/2018/04/1828834381.png) 我把具体内容粘贴到下面: ``` 客户进入:127.0.0.1:14307 客户进入:127.0.0.1:14563 GET / HTTP/1.1 Host: 127.0.0.1:8080 Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Cookie: __uvt=; uvts=6QR1rsXDBappbiwN ``` 没错,这些是浏览器想服务器发送的数据,这个数据是按照一定格式发送的。可以看到,其实浏览器就是个Socket客户端对吧,看到有两个客户端连接了服务端,这里暂不追究为什么是两个客户端。重点就是上面的内容,可以看到,浏览器访问网页的时候主动发送了本地系统属性,接受的编码和语言,以及Cookie。这些就是HTTP协议的一部分,**HTTP协议就是一种规定,我按照规定通过Socket发送内容,可以通过Socket实现HTTP协议的服务端和客户端**。这里注意看`User-Agent`,我是不是可以根据这个判断你是手机还是电脑,判断你用的什么浏览器?一些数据统计平台,也是根据这个信息做统计的。 另外,Socket和HTTP一个明显的区别为:Socket为长连接,就是连接上之后服务端和客户端保持连接状态,双方都可以主动断开;HTTP呢是短连接,浏览器请求一次服务端时,相当于建立的Socket连接,当服务端把数据发送给客户端完成时,服务端主动断开与客户端的连接,一次HTTP请求完成。 ### GET 请求 直白来说,GET请求是显式的,因为你可以在URL里面直接看到GET请求的内容,一般格式为`xxx.com/key1?=value1&key2=value2`,没错,是K-V形式,多个K-V之间&符号连接。比如我正在写这篇文章,后台写作地址为:`xxx/write-post.php?cid=110`,cid就是通过GET请求传递的。 GET请求有长度限制,因为一般URL有长度限制,不易过长。 来做个实验,我用个工具进行GET请求,如下图: ![](/images/2018/04/3587211.png) 实验平台收到的数据为: ``` GET /?key=value HTTP/1.1 Host: 127.0.0.1:8080 Connection: keep-alive User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36 Accept: */* Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Cookie: __uvt=; uvts=6QR1rsXDBappbiwN ``` 看到`GET /?key=value`了吧。 ### POST 请求 POST请求是隐式的,浏览器地址栏里是看不见了,相对Get更为安全一些,所以一般登录用POST,表单也用POST,因为POST可以提交更多的内容。来发个POST试试: ![](/images/2018/04/770381823.png) 接收到的信息: ``` POST /?key=value HTTP/1.1 Host: 127.0.0.1:8080 Connection: keep-alive Content-Length: 0 key1: value1 Origin: chrome-extension://cdjfedloinmbppobahmonnjigpmlajcd User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36 Content-Type: text/plain;charset=UTF-8 Accept: */* Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Cookie: __uvt=; uvts=6QR1rsXDBappbiwN ``` 注意第五行,这就是和GET的区别。其实这个POST貌似没有那么**正宗**(后来发现是用错了,这里添加的是header字段,不是POST)。更多内容请自行百度。 以上演示都是浏览器请求服务端时HTTP协议的应用,服务端返回数据到浏览器时同理,也遵循HTTP规范。 另外,你用浏览器访问网站的时候,F12搞出来开发者工具,观察Network一栏,也能看到所有的请求,请求的细节,内容。一定要会用哦。 自己查查什么是HTTPS?比如我的博客就用来HTTPS来访问。 ### 什么是 DNS 一般访问网站的时候都是输入`网址`,网址其实就是个`域名`,为啥要域名呢,因为你访问一个网站,直接输入`IP`地址记不住啊。比如你访问`feelncut.com`,背后的过程是首先浏览器向`DNS`查询`feelncut.com`对应的`IP`,然后浏览器连接这个IP地址,进行数据通信。`DNS`起到了解析域名到IP地址的作用。拓展,Win或者Ubuntu下`Hosts`文件有什么用? ### Web 默认端口 你访问`baidu.com`的时候为啥没输入端口号呢?因为Web的默认端口是`80`,只要是80端口,就可以省略掉。
可以可以
http://zhangwenxuan.cn/index.php/archives/101/