不会飞的章鱼

熟能生巧,勤能补拙;念念不忘,必有回响。

网络编程基础

OSI七层网络协议

经典协议与数据包

TCP数据包构成

HTTP协议

WebSocket握手协议

WebSocket Data协议

TCP的三次握手与四次挥手

  • 三次握手的最主要目的是保证连接是双工(发送和接收可以同时执行)的,可靠更多的是通过重传机制来保证的。
  • 因为连接是全双工的,双方必须都收到对方的FIN包及确认才可以关闭。

三次握手连接

四次回收关闭

  • 主动关闭方发送FINISH包请求关闭;
  • 被动关闭方回复ACK包表示已经收到这个请求;
  • 被动关闭方完成关闭操作后,回复FINISH包,表示可以关闭了;
  • 主动关闭方再发送一次ACK包表示确认关闭;
  • 两方都进入了CLOSE状态。

为什么time_wait需要等待2MSL?

  • MSL:Maximum Segment Lifetime,30秒-1分钟
  • 保证TCP协议的全双工连接能够可靠关闭
  • 保证这次连接的重复数据段从网络中消失

为什么会出现大量close_wait?

  • 首先close_wait一般出现在被动关闭方
  • 并发请求太多导致
  • 被动关闭方未及时释放端口资源导致

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
func main() {
//1、监听端口
listener, err := net.Listen("tcp", "0.0.0.0:9090")
if err != nil {
fmt.Printf("listen fail, err: %v\n", err)
return
}
//2.建立套接字连接
for {
conn, err := listener.Accept()
if err != nil {
fmt.Printf("accept fail, err: %v\n", err)
continue
}
//3. 创建处理协程
go func(conn net.Conn) {
//defer conn.Close() //TODO:思考-这里不填写会有啥问题?
for {
var buf [128]byte
n, err := conn.Read(buf[:])
if err != nil {
fmt.Printf("read from connect failed, err: %v\n", err)
break
}
str := string(buf[:n])
fmt.Printf("receive from client, data: %v\n", str)
}
}(conn)
}
}

TCP的拥塞控制和流量控制

TCP为什么需要流量控制?

  • 由于通讯双方网速不同,通讯任一方发送过快都会导致对方的消息处理不过来,所以就需要把数据放到缓冲区中;
  • 如果缓冲区已经满了,发送方还在疯狂发送,那接收方只能把数据包丢弃。因此我们需要控制发送速率。
  • 我们缓冲区剩余大小称之为接收窗口,用变量win表示。如果win=0,则发送方停止发送。

TCP为什么需要拥塞控制?

  • 流量控制与拥塞控制是两个概念,拥塞控制是调整网络的负载;
  • 接收方网络资源繁忙,因未及时响应ACK导致发送方重传大量数据,这样将会导致网络更加拥堵
  • 拥塞控制是动态调整win大小,不只是依赖缓冲区大小确定窗口大小。

TCP拥塞控制

  • 慢开始和拥塞避免
  • 快速重传和快速恢复

优化:快重传和快恢复

为什么会出现粘包、拆包,如何处理

基于Golang实现TCP、UDP、HTTP服务器与客户端

------ 本文结束------
如果本篇文章对你有帮助,可以给作者加个鸡腿~(*^__^*),感谢鼓励与支持!