目录
一. 前言
二. 三次握手 (TCP连接建立)
面试灵魂拷问, 为什么是三次握手,而不是二次握手也不是四次握手?
三. 四次挥手 (TCP的连接断开)
面试灵魂拷问2,为什么是四次挥手, 而不是三次
四. HTTP超文本传输协议
啥叫作超文本, URL, DNS?
超文本传输协议HTTP(正式刨析)
然后简单的写一个HTTP服务器 (最简易版本)
五. 总结
https://blog.csdn.net/weixin_53695360/article/details/122989709?spm=1001.2014.3001.5502
https://blog.csdn.net/weixin_53695360/article/details/122754482?spm=1001.2014.3001.5502
https://blog.csdn.net/weixin_53695360/article/details/122790450?spm=1001.2014.3001.5502
上述博客主要针对网络基础比较薄弱的博友们, 有了上述基础后序的知识可以更好的理解和吸收, 后序网络会陆续的刨析所有的网络协议, 希望友友们可以关注互访, 蟹蟹
细节疑惑刨析
上述此处仅暂做简单理解, 后序分析各种协议报文的时候会详解.
上述回答结束OK吗? 当然是OK的, 但是其实存在诸多细节没有刨析
从连接已失效的历史请求报文段的方向来思考为什么必须要三次握手而不是两次握手.
我们类比着三次握手来解释, 三次握手之所以是三次。 是因为第二次的时候是 SYN (同步序号)和ACK(确认应答) 合在了一起, 放在一个报文中发送给了客户端 (此处不懂请回溯)
But : 四次挥手的时候 FIN 和 ACK 不可以放在同一个报文发送给客户端, 这个是为什么?
因为对方(Client)发送FIN 过来 仅仅代表客户端没有数据需要再发送给你服务端了, 但是你服务端可能还有数据需要发送响应给客户端, 所以你服务端暂时不能直接回FIN, 因为一旦回了FIN 就不可以再发送数据了, 所以只能先ACK, 等服务端把当前还需要发送的数据发送完再发送FIN 请求关闭连接. ------ 故此 FIN 和 ACK 需要分开
原理:
一个组织的系统管理机构, 系统内的每个主机的IP和主机名的对应关系.
如果新计算机接入网络, 将这个信息注册到数据库中;
用户输入域名的时候, 会自动查询DNS服务器, 由DNS服务器检索数据库, 得到对应的IP地址.
DNS系统: 是一整套从域名映射到IP的系统
这个状态码感兴趣的看一看就是 咱经常访问哪些 (非法网站的时候) 会弹出 40几呀 50几呀, 懂得都懂3
#include
#include
#include
#include
#include
#include
#include
#define ERR_EXIT(m) \
do { perror(m); exit(EXIT_FAILURE); } while (0)
typedef struct sockaddr SA;
int main(int argc, char* argv[]) {
int connfd, listenfd;
socklen_t buffLen;
char dst[256] = {0};
struct sockaddr_in clientAdd, serveAdd;
if (argc != 2) {
fprintf(stderr, "Usage: %s \n", argv[0]);
exit(EXIT_FAILURE);
}
//域(协议家族), 服务类型, 弃用
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) {
ERR_EXIT("socket error");
}
//确定协议地址簇
serveAdd.sin_family = AF_INET;//协议家族
serveAdd.sin_addr.s_addr = htonl(INADDR_ANY);//确定ip, 通配ip
serveAdd.sin_port = htons(atoi(argv[1]));//确定绑定端口号
//bind绑定固定端口号便于接收连接请求
if (bind(listenfd, (SA*)&serveAdd, sizeof(serveAdd)) == -1) {
ERR_EXIT("bind error");
}
//开始监听
if (listen(listenfd, 3) == -1) {
ERR_EXIT("listen error");
}
fprintf(stdout, "wait accept:\n");
for ( ;; ) {//循环接收客户端的请求
buffLen = sizeof(clientAdd);
if ((connfd = accept(listenfd, (SA*)&clientAdd, &buffLen)) == -1) {
ERR_EXIT("accept error");
}
printf("accept connection from ip is %s and port is %d \n",
inet_ntop(AF_INET, &clientAdd.sin_addr, dst, sizeof(dst)),
ntohs(clientAdd.sin_port));
char input_buff[1024 * 10] = {0}; //开足够大的空间写入数据
ssize_t read_size = read(connfd,input_buff, sizeof(input_buff) - 1);//留一个结束字符
if (read_size == -1) {
ERR_EXIT("read error");
}
printf("[Request] %s", input_buff);
char buff[1024] = {0};
const char* hello = "hello hhtp
";
sprintf(buff, "HHTP/1.0 200 OK\nContent-Length:%lu\n\n%s", strlen(hello), hello);//按照hhtp规矩写入
write(connfd, buff, sizeof(buff));
}
exit(EXIT_SUCCESS);
}
备注: 此处我们使用 9090 端口号启动了HTTP服务器. 虽然HTTP服务器一般使用80端口,
但这只是一个通用的习惯. 并不是说HTTP服务器就不能使用其他的端口号.
使用chrome测试我们的服务器时, 可以看到服务器打出的请求中还有一个 GET /favicon.ico HTTP/1.1 这 样的请求.
- 首先本文描述了三次握手, 核心关键在于 为什么是三次不是二次也不是四次?
- 简单解释是: 为了使得确定客户端服务端双放的收发数据的正常, 确立双方稳定的数据通信的连接, 从避免历史包的接收建立服务端的无效连接浪费服务端资源的角度再理解了一下为啥两次连接不行, 四次乃至更多次的连接不是不可以而是没有必要, 浪费资源
- 四次挥手重点, 为啥是四次挥手不是三次? 核心点在于 这个 FIN + ACK为啥不能何在一起? (此处你应该能自己回答出来)不能请回溯
- 最后介绍HHTP 应用层协议: 超文本传输协议, 其实还有 FTP:文件传输协议等等 都是再应用层上的协议, HHTP : 超文本传输协议, 和我们平时使用的网页网站强相关, 所谓网页就是多个超链接连接一次构成的网状结构. 网站可以理解为存储多个网页的服务端.
- DNS 域名系统, 为了解决IP地址不好记忆的问题, 搞出来了IP映射的这样一个域名系统, 可以利用域名映射IP地址 + 端口号访问服务器,
- URL : 服务类型 域名(IP) 端口号 文件路劲 资源定位
- GET 从网站中获取网页 POST: 向网站中post网页
- HTTP 是建立的一次TCP连接的基于TCP在其之上的应用层协议
- HTTP 多次不断的进行TCP的连接和断开连接的效率低下方面的解决措施: 搞出来了持久连接 (连接保持一段时间)
- 无状态性 : 不会记录之前是否访问, 简化服务器设计, 更容易支持大量并发