问:hosts 文件在哪?
答:
- 在 Windows 系统中,hosts 位于 C:\Windows\System32\drivers\etc\hosts 。
- 在 macOS / Linux系统中,hosts 位于 /etc/hosts
URL - Uniform Resource Locator 统一资源定位符
统一资源定位符的标准格式如下:
URI = scheme:[//authority]path[?query][#fragment]
[协议类型]://[服务器地址]:[端口号]/[资源层级UNIX文件路径][文件名]?[查询]#[片段ID]
协议类型:http, https, ftp ...
服务器地址:域名或IP
端口:提供服务的端口号
路径:UNIX文件路径
查询:query string,也叫查询参数,可被服务器接收和识别
片段/锚点:fragment 可用于定位到页面上的指定位置
查看本机IP设置
windows: ipconfig
mac: ifconfig
loopback: 127.0.0.1 localhost
Port 端口
计算机之间依照互联网传输层TCP/IP协议的协议通信,不同的协议都对应不同的端口。
- 0-1023:官方端口,应用与端口组合记录在IANA的端口分配列表中
- 1024-49151:非官方 应用与端口组合不在IANA的端口分配列表中
- 49152-65535:根据定义,该段端口属于“动态端口”范围,没有端口可以被正式地注册占用。
常用端口: HTTP:80,替代端口为8080 HTTPS:443 FTP:21(控制端口,常用),20(默认数据端口) SSH:22 DNS:53
端口被占用是个非常常见的情况,如果发现被占用换一个就行。
ping 工具
ping利用ICMP返回包来计算网络的丢包率和RTT 用法
- Ping the specified host:
ping host
- Ping a host a specific number of times:
ping -c count host
DNS - Domain Name System
域名对应IP,方便用户记忆。
负载均衡:域名对应多个IP,防止压力过大。
共享主机:IP对应多个域名。
nslookup 工具 查询域名
向DNS发出请求,获得域名和对应IP。
理论上的网页请求顺序: html -> css -> js 网页内容按顺序请求,因而应合理排布网页内容。
域名层次:
域名由多个部分组成,这些部分通常连接在一起,并由点分隔。
-
顶级域名: 顶级域(英语:Top-level domains,缩写:TLD)是域名中最高的一级,每个域名都以顶级域结尾。
.com .cn .org. .gov均属于顶级域名 -
子域名: 二级域名:
位于顶级域名的左侧。
对于 wikipedia.org来说:
wikipedia是一个‘二级域名’。
而 wikipedia.org可被称为‘一级域名’
三级域名:
位于二级域名的左侧。
对于 zh.wikipedia.org来说:
zh是一个‘三级域名’。
而zh.wikipedia.org可被称为‘二级域名’
也即 `www.wikipedia.org` 和 `wikipeida.org` 并不是一个域名,前者为二级域名,后者为一级域名。
所有带www的网站会被默认指向它的一级域名。
Query String 查询参数
GET模式的窗体参数:
以“?”字符为起点,每个参数以“&”隔开,再以“=”分开参数名称与资料,通常以UTF8的URL编码,避开字符冲突的问题
Fragment 锚点/片段
片段。以“#”字符为起点,可迅速定位到页面的指定位置(锚点)
锚点不支持中文。
锚点会被浏览器接收,但不会发送给服务器。
URL中的中文
实际上URL本身是不支持中文的,URL的中文会根据UTF-8转码,每个字节前加上%,形成URL编码。
在浏览器地址栏里,浏览器认为%是个转义字符,浏览器会把%与%之间的编码,两位两位取出后进行解码,然后再传递给后端,然后由后端进行再次解码。
encodeURI()方法可对字符串进行转义,形成URL编码。
decodeURI()方法可还原转义后的URL片段,为encodeURI的逆运算。
HTTP
HTTP规格文档:RFC2612
HTTP 请求与响应
可参考的内容: www.liaoxuefeng.com/wiki/101695…
User-Agent -> Server
GET请求和POST请求的区别:
GET只向服务器发送header data,POST请求除了header data以外附带一个body,里面包含用户数据。
此外GET是明文请求,而POST请求并不对外显示。
HTTP Request (RFC 2612 Chapter5)
request格式:
- Request header
请求动词 路径和查询参数 协议名/版本
Host: 域名或IP
Accept: 可接受的内容,e.g. text/html<br>
Content-Type: request body所含内容的格式
-- 请求动词:GET / POST / PUT / PATCH / DELETE
- Request body GET请求一般不含body,post会带有上传的内容。
HTTP Response (RFC 2612 Chapter6)
Response格式:
- Response header
协议名/版本 状态码 状态字符串
Content-Type: response body所含内容的格式
- Response body 响应内容,也就是下载内容
Status Code 状态码
cURL
curl命令是一个利用URL规则在命令行下工作的文件传输工具。它支持文件的上传和下载,所以是综合传输工具,但按传统,习惯称curl为下载工具。作为一款强力工具,curl支持包括HTTP、HTTPS、ftp等众多协议,还支持POST、cookies、认证、从指定偏移处下载部分文件、用户代理字符串、限速、文件大小、进度条等特征。做网页处理流程和数据检索自动化,curl可以助一臂之力。
curl发送HTTP请求
可参考以下文档学习curl: man.linuxde.net/curl
curl -v:
verbose 详细模式
-v, --verbose
Makes curl verbose during the operation. Useful for debugging
and seeing what's going on "under the hood". A line starting
with '>' means "header data" sent by curl, '<' means "header
data" received by curl that is hidden in normal cases, and a
line starting with '*' means additional info provided by curl.
If you only want HTTP headers in the output, -i, --include might
be the option you're looking for.
If you think this option still doesn't give you enough details,
consider using --trace or --trace-ascii instead.
Use -s, --silent to make curl really quiet.
简而言之verbose模式会提供详细的请求内容。
>代表发出的header data
<代表收到服务器返回的header data
从curl的运行的结果中可以看出:
- DNS请求得到域名对应的IP,通过80端口访问。
- 随即建立TCP连接
- 发送请求,包含访问方法(GET),指定host,user-agent(curl),以及期待返回的内容(
*/*代表所有内容均接受) - 获得反馈,status code 200 OK
- 反馈里包含header data和网页的实际内容
- 关闭TCP连接
- 结束程序
由于这次访问没有包含www, baidu 只返回了meta。
用同样的方法访问 bing.com, 得到302 Found, 访问 www.bing.com 则得到301 Moved Permanently,都不会返回完整内容,需要重新定向。
-X 请求动词
e.g. curl -X POST http://localhost:8888/xxx?test=hi
-H 'Name:Value' 或者 --header 'Name:Value':设置请求头
e.g. curl -H 'Accept:text/html' http://localhost:8888/xxx?test=hi
Node.js实现一个简单的请求和响应
可参考文档: nodejs.org/zh-cn/docs/…
var http = require('http');
var fas = require('fs');
var url = require('url');
var port = process.argv[2];
if (!port) {
console.log('Please set a Port number: ');
process.exit(1);
}
var server = http.createServer(
function (request, response) {
/* 基本参数 */
var parsedURL = url.parse(request.url, true);
var pathWithQuery = request.url;
var queryString = '';
if (pathWithQuery.indexOf('?') >= 0) {
queryString = pathWithQuery.substring(pathWithQuery.indexOf('?'));
}
var path = parsedURL.pathname;
var query = parsedURL.query;
var method = request.method;
/* 收到request并打印其路径和参数 */
console.log('New request - Path and Query: ' + pathWithQuery);
/* 根据request path返回不同的response header */
if (path === '/') {
response.statusCode = 200;
response.setHeader('Content-Type', 'text/html;charset=utf-8');
response.write(`root`);
response.end();
}
else if (path === '/x') {
response.statusCode = 200;
response.setHeader('Content-Type', 'text/css;charset=utf-8');
response.write(`body{color: red;}`);
response.end();
}
else {
response.statusCode = 404;
response.setHeader('Content-Type', 'text/html;charset=utf-8');
response.write(`The path does not have any content`);
response.end();
}
}
)
server.listen(port);
console.log('Listen ' + port + ' successfully. You can open the page through http://localhost:' + port);
结果:
通过Chrome,Safari和curl各发了一次请求
Node.js 读取请求
- 读取请求动词:
request.method - 读取url(带查询参数):
request.url - 读取纯路径path:`request.path
- 读取查询参数:
request.query - 读取请求头:
request.headers[]
Node.js 设置响应
- 设置状态码:
response.statusCode = <codeNumber>; - 设置响应头:
response.setHeader('Name', 'Value'); - 设置响应体:
response.write('Content');
解决Mac上的端口占用问题
启动服务失败有可能是该端口已被占用。
- 可使用
lsof -i tcp:<port>查询指定端口已启用的服务。 - 使用
kill <PID>干掉该进程,解除端口占用。