【传输层协议TCP/UDP】

 1 PORT协议(端口协议)
 2     端口号用来(ip+port):标识一台计算机上面的某一个应用程序
 3     端口号的范围:0-65535
 4     这是因为传输层的协议:TCP、UDP等,它们的报头端口号长度是16bit所决定的!! 2的16次方
 5     端口号特征:动态分配(类似于洗浴中心号码牌)
 6     每一个应用程序都要有一个端口号!!!
 7 
 8 ----------------------------------------------------------
 9 
10 # 建议:
11 0-1024    系统默认需要使用的端口号,操作系统里面有一些固定的底层服务需要用的。别使用这些端口号!!
12 1024-8000    常见软件的端口号,可能已经被占掉了,也尽量别用!
13 8000之后的    以后写项目推荐使用!!!
14 
15 软件在启动的时候是可以指定端口号的,就是说自己可以去指定用哪个端口号的,常用的已经被指定完了,
16 不指定一个端口号,就会被计算机动态的分配一个端口号!!!
17 
18 注意,端口号是不固定的,即可以由用户手工可以分配(当然,一般在软件编写时就已经定义)。
19 当然,有很多应用软件有公认的默认的端口,比如FTP:20和21,HTTP:80,TELNET:23等等
20 一个软件可以拥有多个端口号,这证明这个软件拥有不止一个网络功能。
21 
22 ------------------------------------------------
23 URL:统一资源定位符(网址)
24 网址本质是有IP和PORT组成的!!!!
25 
26 ------
27 
28 IP:PORT:能够定位全世界独一无二的一台计算机上面的某一个应用程序
29     114.55.205.139:80
30 ------
31 
32 我们之所以不直接使用IP+PORT的原因是太难记 所以发明了域名(网址)
33 域名解析:将网址解析成IP+PORT

---------------------------------------------

重点!!!!!!

 1 # TCP与UDP都是用来规定通信方式的
 2 
 3 TCP协议(传输控制协议)
 4     当应用程序希望通过 TCP 与另一个应用程序通信时,它会发送一个通信请求。
 5     这个请求必须被送到一个确切的地址。在双方“握手”之后,TCP 将在两个应用程序之间建立
 6     一个全双工 (full-duplex) 的通信。这个全双工的通信将占用两个计算机之间的通信线路,
 7     直到它被一方或双方关闭为止。
 8     tcp协议就是控制数据数据包在传输过程中的规范格式
 9     是一种面向连接的,可靠的,基于字节流的传输层协议。
10 
11 
12 (Transmission Control Protocol)传输控制协议
13 通俗地说TCP就是对于传输、发送、通信进行控制的协议。
14 
15 
16 1.TCP协议(重要)
17 TCP协议的特点是:面向连接、字节流、可靠传输
18 TCP的机制具有:校验机制、可靠、数据传输稳定
19 
20 ---------------------------------------------
21 # 三次握手:建链接
22     1.TCP协议也称为可靠协议(数据不容易丢失)
23         造成数据不容易丢失的原因不是因为有双向通道,而是因为有反馈机制!!!!!
24         给对方发消息之后会保留一个副本 直到对方回应消息收到了才会删除
25         否则会在一定的时间内反复发送
26 
27 
28     2.洪水攻击
29         同一时间有大量的客户端请求建立链接,会导致服务端一直处于SYN_RCVD状态!!!!
30     3.服务端如何区分客户端建立链接的请求
31         可以对请求做唯一标识
32 ---------------------------------------------
33 
34 # 四次挥手:断链接
35     1.四次不能合并为三次
36         因为中间需要确认消息是否发完(TIME_WAIT)
37 
38 ---------------------------------------------
39 ps:课下可以深入研究一下TCP图片上每个状态的具体情况
40 
41 需要注意:
42 TCP协议用于1对1,即不能用于基于广播和多播的应用程序
43 TCP连接双方的收发数据次数不一定相同,即发送多次的数据包,可能会被对方1次全部接收
44 TCP在发送数据报后,必须得到接收方的应答,才认为传输成功,所以是可靠的
45 TCP采用超时重传机制,超过时间没收到应答,就会重新发送。

(三次握手)

三次握手建立通道:建立链接是为了传数据做准备的,三次握手即可
    1.客户端发送syn包---->服务器
    2.服务器收到syn包,发送ack确认包---->客户端
    3.客户端收到ack确认包,发送ack确认包---->服务器
    三次握手完毕,建立双向通道


(四次挥手)

   四次挥手断开通道:断开链接是为了节省资源做准备的,四次挥手即可
    1.客户端发送fin包---->服务器
    2.服务器收到fin包,发送ack确认包---->客户端
    3.服务器发送fin包---->客户端
    4.客户端收到fin包,发送ack确认包---->服务器
    四次挥手完毕,断开双向通道


 

PS补充:

1 PS:当服务端大量处于TIME_WAIT状态时,会导致端口资源耗尽,无法建立新的链接
2    基于udp协议通信:不需要建立双向通信的通道
3     C<--------------------S
4     S<--------------------C
5     udp协议:不可靠传输,速度快,但是容易丢包

tcp半链接池:(相当于一个等待服务窗口:如网上客服咨询等待)backlog

【链接请求1,链接请求2,链接请求3.。。】

【应用层】

应用层相当于是程序员自己写的应用程序,里面的协议非常的多

常见的有:HTTP、HTTPS、FTP

ps:后续框架部分再做介绍

 

【socket套接字】

socket是网络通信中的一个抽象概念,它是一个通信链的句柄,可以用来实现不同主机之间的进程通信
  import socket

 1 如果我们需要编写基于网络进行数据交互的程序
 2 意味着我们需要自己通过代码来控制我们之前所学习的OSI七层(很繁琐 很复杂 类似于我们自己编写操作系统)
 3 
 4 socket类似于操作系统 封装了丑陋复杂的接口提供简单快捷的接口
 5 -----------------------------------------
 6 
 7 理解socket
 8 Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,
 9 Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,
10 一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
11 
12 -----------------------------------------
13 
14 Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,
15 一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
16 
17 -----------------------------------------
18 
19 socket也叫套接字
20     基于文件类型的套接字家族(单机)
21     AF_UNIX
22 -------------
23     基于网络类型的套接字家族(联网)
24     AF_INET
25 
26 -----------------------------------------
27 
28 在这里主要学习利用socket完成TCP/IP通讯,首先需要生成两个对象,
29 一个是客户端(client),一个是服务端(sever)。

 

 

(工作流程)

(基于tcp协议的简单套接字)

  PS:为什么要先运行服务端,再运行客户端?
      因为客户端需要连接服务端,所以服务端必须先运行起来,等待客户端的连接。
      而客户端是主动连接服务端的,所以客户端可以先运行起来。

 1 服务端
 2 
 3 import socket
 4 
 5 # 1.买手机
 6 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # AF_INET:表示ipv4,SOCK_STREAM:表示使用tcp协议
 7 
 8 # 2.绑定手机卡  ip+端口,如果ip是:0.0.0.0,表示本机的所有ip都可以使用
 9 phone.bind(("127.0.0.1", 8082))  # (绑定的是服务端的id)0-65535,1024以前的被系统保留使用
10 
11 #  3.开机,监听状态
12 phone.listen(5)  # 5表示半链接池的大小(backlog=5)
13 print('服务端启动完成,监听地址为:%s:%s' % (socket.gethostname(), 8082))
14 
15 # 4.等待电话链接请求
16 # conn:表示与客户端进行通信的socket,client_addr:表示客户端的ip和端口
17 conn, client_addr = phone.accept()
18 print(conn)
19 print('客户端的ip和端口:', client_addr)
20 
21 # 5.接收消息\发送消息
22 data = conn.recv(1024)  # 1024表示一次接收1024个字节
23 print('客户端发送的数据:', data.decode('utf-8'))
24 conn.send(data.upper())  # 将接收到的数据转换为大写,并发送给客户端
25 
26 # 6.关闭连接
27 conn.close()
28 
29 # 7.关闭手机(可选操作,可有可无)
30 phone.close()
31 
32 
33 -------------------------------------------------------------------------------------
34 客户端
35 
36 
37 import socket
38 
39 
40 # 1.买手机:AF_INET--地址家族,实现网络通信  SOCK_STREAM---基于什么协议:流式协议(tcp)
41 # SOCK_DGRAM---数据报协议(udp)
42 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
43 
44 # 2.拨通服务端电话,发送连接请求
45 phone.connect(('127.0.0.1', 8082))  # connect()括号里是服务端ip和端口号=client_addr
46 
47 # 3.通信
48 phone.send('hello tank 早上好'.encode('utf-8'))
49 
50 # 4.关闭连接,对应的是服务端的conn
51 phone.close()

 (通信循环--解决Bug)

 1 # 5.接收消息\发送消息
 2 while True:
 3     try:
 4         data = conn.recv(1024)  # 1024表示本次接收的最大字节数,收到的是bytes类型
 5         if len(data) == 0:
 6             # 在unix/linux下,一旦data收到的是空,就意味着是一种异常的行为:客户端非法断开了链接
 7             break
 8         print('客户端发来的消息:', data.decode('utf-8'))
 9         conn.send(data.upper())
10     except Exception:
11         # 针对windows系统客户端非法断开解决办法
12         break
13 
14 --------------------------------------------------
15 客户端
16 
17 # 3.通信
18 # 客户端如果强行断开连接,会造成服务端死循环
19 while True:
20     msg = input('输入要发送的消息>>:').strip()
21     #  输入空格,不发送,如果输入空,客户端会阻塞
22     if len(msg) == 0: continue
23     # 退出循环
24     # if msg == 'quit': break
25     # time.sleep(2)
26     # phone.send(b.ini'hello')  # phone.send('hello'.encode('utf-8')),必须是bytes类型
27     phone.send(msg.encode('utf-8'))
28     print('=====?')  # 验证什么造成了阻塞,阻塞在哪里
29     data = phone.recv(1024)  # 上面一行代码运行,说明收阻塞了
30     print(data.decode('utf-8'))

(链接循环案例)

服务端应该满足的特点:
  1.一直提供服务
  2.并发的提供服务

 1 服务端
 2 
 3 import socket
 4 
 5 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 6 
 7 # 2.绑定手机卡
 8 phone.bind(("127.0.0.1", 8083))
 9 
10 #  3.开机
11 phone.listen(5)
12 print('服务端启动完成,监听地址为:%s:%s' % (socket.gethostname(), 8083))
13 
14 # 4.等待电话链接请求,拿到电话连接conn
15 # 当上一客户服务完成,接待下一个客户的做法:
16 # 链接循环
17 while True:
18     conn, client_addr = phone.accept()
19     print('客户端的ip和端口:', client_addr)
20 
21     # 5.接收消息\发送消息
22     while True:
23         try:
24             data = conn.recv(1024)
25             if len(data) == 0:
26                 break
27             print('客户端发来的消息:', data.decode('utf-8'))
28             conn.send(data.upper())
29         except Exception:
30             # 针对windows系统客户端非法断开解决办法
31             break
32 
33     # 6.关闭连接
34     conn.close()
35 
36 # 7.关闭手机
37 phone.close()
38 
39 
40 ------------------------------------------------------------------------------------
41 客户端1:
42 
43 import socket
44 import time
45 
46 
47 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
48 
49 # 2.拨通服务端电话
50 phone.connect(('127.0.0.1', 8083))
51 
52 # 3.通信循环
53 while True:
54     msg = input('输入要发送的消息>>:').strip()
55     if len(msg) == 0: continue
56     # 退出循环
57     # if msg == 'quit': break
58     # time.sleep(2)
59     # phone.send(b.ini'hello')  # phone.send('hello'.encode('utf-8')),必须是bytes类型
60     phone.send(msg.encode('utf-8'))
61     print('=====?')
62     data = phone.recv(1024)
63     print(data.decode('utf-8'))
64 
65 # 4.关闭连接
66 phone.close()
67 
68 
69 
70 ===========================================
71 当其中一个客户端断开连接,第二个客户端发送建立连接请求,服务端能继续服务

 

【半链接池】

 1 定义:
 2 半连接池是一个容器或机制,用于存储和管理在网络通信中形成的半连接状态。
 3 
 4 背景:
 5 在TCP协议中,建立连接的过程包括三次握手。当客户端发送SYN包到服务器,服务器响应ACK包并等待客户端的确认时,这种状态被称为半连接状态。
 6 在高并发的网络环境中,如果短时间内有大量客户端发起连接请求,服务器可能会因为处理不过来这些半连接状态而导致资源耗尽,进而影响服务性能。
 7 
 8 工作原理:
 9 当客户端请求成功被服务端接收后,服务端不会立即对该请求发出响应,而是将这些请求存储在半连接池中。
10 只要半连接池没有满,客户端的请求都会进入服务端。如果半连接池已满,新的请求将被阻拦并显示等待。
11 半连接池通过服务端响应最早进入的客户端请求,达到管理半连接状态、防止资源耗尽的目的。
12 
13 作用:
14 限制同一时间内的客户端请求数,避免服务器因处理过多半连接状态而资源耗尽。
15 提高服务器在高并发环境下的稳定性和性能。
16 
17 相关概念:
18 SYN洪水攻击:一种网络攻击方式,通过不断产生半连接状态,让服务器无法处理正常请求。
19 连接池:一种通用的技术,用于提高资源的利用率和系统的性能。除了半连接池外,还有数据库连接池、线程池等。
20 注意:
21 半连接池限制的是同一时间的客户端请求数,而非连接数。
22 合理地配置半连接池的大小对于服务器的性能和稳定性至关重要。

 。

(udp协议套接字)

 1 服务端
 2 
 3 import socket
 4 
 5 server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # 数据报协议==》udp协议
 6 
 7 server.bind(('127.0.0.1', 8083))
 8 
 9 while True:
10     data, client_addr = server.recvfrom(1024)
11     server.sendto(data.upper(), client_addr)
12 
13 server.close()
14 
15 
16 -----------------------------------------------------------------------------------
17 客户端
18 
19 import socket
20 
21 client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
22 while True:
23     msg = input('>>:').strip()
24     client.sendto(msg.encode('utf-8'), ('127.0.0.1', 8083))
25     res = client.recvfrom(1024)
26     print(res)
27 
28 client.close()

 

 

(UDP和TCP的区别)

 1 TCP与UDP都是用来规定通信方式的
 2 区别:
 3   TCP协议称之为流式协议、可靠协议(数据不容易丢失)
 4     面向连接
 5   UDP协议称之为数据报协议、不可靠协议
 6     面向无连接
 7     
 8 # UDP用在哪里?
 9 早期的QQ使用的就是纯生的UDP协议
10 现在QQ自己添加了很多技术和功能
11   使用UDP的原因就是因为很简单 快捷 粗暴 只要指定对方的地址就可以发消息了 而TCP还要建立三握四挥
12     
13 TCP我们可以打比方为打电话 你一句我一句
14 UDP我们可以看成是发短信 只要发了就行 不管对方看不看

 。

【粘包问题,UDP协议没有粘包问题】

(1)什么是粘包问题

 

posted on 2024-06-20 22:11  认真的六六  阅读(15)  评论(0编辑  收藏  举报