TCP/IP 是供已连接因特网的计算机进行通信的通信协议。
HTTP 协议的底层其实是由 TCP 协议(规定如何传输)和 IP 协议(规定如何连网)(简称 TCP/IP协议)构建的。
TCP和UDP的区别
三次握手和四次挥手
用node.js做服务器,并发出http响应
TCP 传输控制协议(Transmission Control Protocol)
TCP面试题
问:TCP 和 UDP 的区别是什么
简答:TCP 可靠(能够知道发送的请求是否成功)、面向连接、相对 UDP 较慢;UDP 不可靠,不面向连接、相对 TCP 较快。 补充:
- 什么叫面向连接呢?事先为所发送的数据开辟出连接好的通道,然后再进行数据发送。【像打电话,只能两人打,第三人打就显示占线。】
- 非面向连接:是指通信双方不需要事先建立一条通信线路,而是把每个带有目的地址的包(报文分组)送到线路上,由系统自主选定路线进行传输。【就像写信,不管对方有多忙,把信放到邮筒,就与自己无关系了。】
问:TCP 的三次握手指的是什么
简答:每次建立连接前,客户端和服务端之前都要先进行三次对话,成功后才开始正式传输内容,三次对话大概是这样的:
- 客户端:我要连接你了,可以吗(浏览器向服务器发送建立连接的请求。)
- 服务端:嗯,我准备好了,连接我吧(服务器接收到浏览器发送的请求后,向浏览器发送同意连接的信号。)
- 客户端:那我真的连接你咯。(浏览器接受到服务器发出的同意连接的信号后,再次向服务器发出确认连接的信号。)
- 三次握手完成,客户端和服务端成功的建立TCP连接,就可以开始传输数据了。(客户端发送http请求的4个部分给服务端,服务端接收请求并处理后,发送http响应的4个部分给客户端。客户端接收响应)
这是因为,TCP要建立连接,必须确认4件事
- 客户端可以发请求
- 服务端可以收请求,服务端可以发请求
- 客户端可以收请求
问:TCP 的四次挥手指的是什么
答:
- 浏览器向服务器发送一个断开连接的请求(你把我断开吧);
- 服务器接到请求后发送确认收到请求的信号(知道了);
- 服务器向浏览器发送断开通知(那我把你断开咯?);
- 浏览器接到断开通知后断开连接并反馈一个确认信号(嗯,你断吧),服务器收到确认信号后断开连接
为什么服务器在接到断开请求时不立即同意断开:当服务器收到断开连接的请求时,可能仍然有数据未发送完毕,所以服务器先发送确认信号,等所有数据发送完毕后再同意断开。
IP 网络协议(英语:Internet Protocol)
IP 分为「内网 IP」 和「外网 IP」
- 路由器有两个 IP,一个外网 IP(每次重启路由器后会重新分配一个新的外网IP)和一个内网 IP(192.168.1.1)
127.0.0.1 localhost
本地ip,表示设备自己- 还有一个特别特殊的 IP:0.0.0.0,它不表示任何设备。
端口(Port)
如果一个服务器既提供 HTTP 服务,又提供 FTP 服务,还提供 SMTP 服务(邮件服务),那么只用一个 IP 是无法告诉服务器你想要使用哪种服务。
所以这里有一个重要的原则:一个端口对应一个服务。
要提供 HTTP 服务使用 80 端口
12访问https://www.baidu.com实际上是访问https://www.baidu.com:80浏览器帮你加了默认端口号 80。要提供 HTTPS 服务使用 443 端口
- 要提供 FTP 服务使用 21 端口
总结:使用 HTTP 协议访问另一个 IP 时,必须同时提供 IP 和端口号,缺一不可。
用Node.js创建一个服务器
接收请求
我们的脚本只需要一个文件就可以搞定
- 新建一个目录
cd ~/Desktop; mkdir node-demo; cd node-demo
touch server.js
- 编辑 server.js,内容我已经上传到 GitHub。
- 或者
curl https://raw.githubusercontent.com/FrankFang/nodejs-test/7f1a0ce15c47a6c2c938fe322f042e5d62bc7d01/server.js > ./node-demo/server.js
将代码下载到server.js文件内 - 运行
node server.js
,看到报错 - 根据报错提示调整你的命令
- 成功之后,这个 server 会保持运行,持续监听,无法退出
- 如果你想「中断」这个 server,按
Ctrl + C 即可(C 就是 Cancel 的意思) - 中断后你才能输入其他命令
- 我建议你把这个 server 放在那里别动,新开一个 Bash 窗口,完成下面的教程
curl -s -v -- http://qq.com/xxx?name=ff
,其中查询参数是?name=ff
,查询参数是包含问号的
好了服务器完成。只不过
- 这个服务器目前只有一个功能,那就是打印出路径和查询字符串
- 还缺少一个重要的功能,那就是发出 HTTP 响应
目前我们先只做一个功能玩玩。
接下来你要发起一个请求到这个服务器。这听起来有点怪异,「我向自己发起请求」,目前是的,因为你买不起服务器啊。
在新的 Bash 窗口运行 curl http://localhost:你的指定的端口/xxx?name=yyyy
或者 curl http://127.0.0.1:你指定的端口/xxx?name=yyyy
。
你会马上发现 server 打印出了路径:
这说明我们的 server 收到了我们用 curl 发出的请求
由于 server 迟迟没有发出响应,所以 curl 就一直等在那里,无法退出(用
发出响应
接下来我们让我们 server 发出响应
- 编辑 server.js
在中间我标注的区域添加两行代码
12345678910console.log('方方说:得到 HTTP 路径\n' + path)if (path == '/') {response.write('Hi\n')} else if (path == '/index') {response.setHeader('Content-Type', 'text/html; charset=utf-8')response.write('<!DOCTYPE html>\n<head><body><h1>你好</h1></body></head>')} else {response.statusCode = 404}response.end()Ctrl+C 中断之前的 server,重新运行
node server.js 8888
curl http://127.0.0.1:8888/xxx
,结果如下:1Hi%
这个 % 不是我们的内容,% 表示结尾。
- 好了,响应添加成功
- 使用
curl -s -v -- "http://localhost:8888/xxx"
可以查看完整的请求和响应
根据请求返回不同的响应
- 响应 /
- 响应 /xxx
- 响应 404
- 响应 /xxx.html
- 响应 /xxx.frank
- 再次强调,后缀是废话。文件内容是有 HTTP 头中的 Content-Type 保证的
- 响应 /xxx.css
- 响应 /xxx.js
- HTTP 路径不是文件路径!!!/xxx.html 不一定对应 xxx.html 文件
完整代码