由于不同机器上的程序要通信,才产生了网络
C/S架构
server 服务端
client 客户端
服务端 是 要一直运行 等待服务别人
客户端 是 我用的时候 我才去用
B/S架构
server 服务端
broser 浏览器
使用浏览器去访问的服务 就是一个B/S架构的服务
b/s 和 c/s架构是什么关系
b/s架构是c/s结构的一种
网络编程
就是基于网络之间的两个程序要通讯
想要实现通信
得有 网卡 和 网线
网卡上 有 全球唯一的 mac地址 是电脑上的身份证
找到了mac地址,就找到了这台电脑
规定网络地址的协议叫IP协议,它定义的地址称之为ip地址,广泛采用的v4版本即ipv4,它规定网络地址由32位2进制表示。
4个8位2进制数:00000000.00000000.00000000.00000000
范围 0.0.0.0 - 255.255.255.255
一个ip地址通常写成四段十进制数,例:172.16.10.1
127.0.0.1 本地回环地址
交换机的出现解决了多台电脑的通信问题
网关的概念 -- 局域网中的机器想要访问局域网外的机器,需要通过网关访问
ip地址 和 子网掩码 按位与 得到网段地址
总结:ip协议的作用主要有两个,一个是为每一台计算机分配ip地址,另一个是确定哪些地址在同一个子网络。
端口 为了找到计算机上的程序
在计算机上 每一个需要网络通信的程序 都会开一个端口
在同一时间只会有一个程序占用一个端口
不可能在同一时间 有两个程序 占用同一个端口
端口的范围:0-65535
如果自己想要开一个端口 一般情况下 是 8000之后的端口
假设 你有一个
ip -- 你就能确定唯一一台机器
端口 -- 确定唯一的一个程序
既有ip 又有端口 就可以从茫茫网络中找到唯一的一台机器上的唯一的一个程序
计算机之前的通讯
tcp协议 和 udp协议
TCP协议
当应用程序希望通过TCP与另一个应用程序通信时,它会发送一个通信请求。
这个请求必须被送到一个确切的地址。在双方“握手”之后,TCP将在两个应用程序之间建立
一个全双工的通信。
这个全双工的通信将占用两个计算机之间的通信线路,直到它被一方或双方关闭为止。
全双工:
假设有一个client端 和 server端,c可以向s发送请求,s可以接受,
并且s也可以向c发送请求,c接受,这就是全双工。
(双方可以互发信息并接收)
TCP的连接过程
建立连接三次握手
client------------->server 一次
(SYN seq=x)
<---------------- 二次
(SYN seq=y ACK=x+1)
------------------> 三次
(ACK=y+1)
断开连接四次挥手
client----------------->server 一次
(FIN seq=x+2 ACK=Y+1)
<--------------------- 二次
(ACK x+3)
<--------------------- 三次
(FIN seq=y+1)
-------------------->
(ACK=y+2) 四次
全双工: =======================》 一条
《====================== 二条
注释:c端不想与s端建立连接了,发送了一个请求,说咱们两断开吧。
s端回复请求,说好。这是全双工中的一条连接断开。
这就相当于c端嘴不能说话了,但是耳朵还可以听到。这时s端还可以说话
,s端也发送一个请求说那我也断开吧,c端回复说好,这时全双工的另一条也断开了,
这就完完全全的断开了,都说不了,听不到。
为什么三次握手四次挥手?
发起关闭的这个请求,你只能控制你自己的嘴巴,你不能去控制其他人的嘴巴。
发起请求是,建立的肯定是一个全双工的连接,你请求我同意,我请求你同
意,中间的那两步可以合并。
但是断开连接时,是一个全双工的通信,你只能管理你自己,不能管理其他人,
c端断开连接时,只是c端不能发信息了,但是s端还是可以c断发送信息的,
所以断开连接时需要四次挥手。
UDP协议
当应用程序希望通过UDP与一个应用程序通信时,传输数据之前源端和终端不建立连接。
当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。
tcp与udp对比
tcp--传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器
彼此交换数据前,必须在双方之间建立一个tcp连接,之后才能传输数据。tcp提供
超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。
udp--用户数据协议,是一个简单的面向数据报的运输层协议。udp不提供可靠性,
它只是把应用程序传给ip层的数据报发送出去,但是并不能保证它们能否到达目的地。
由于udp在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发
机制,故而传输速度很快。
tcp就是打电话 如果传重要的东西,就用tcp
udp就是发短信 qq用的就是udp协议 速度快
网络的协议可以理解为是一个包快递和拆快递的过程
应用层 (“你好”) 应用层
传输层 (选择通信协议tcp udp) 传输层
网络层 (ip协议 给上一层消息 网络层
又加上了ip信息)
数据链路层 (mac地址) 数据链路层
物理层(网卡 网线) (网卡 网线)物理层
顺序是:从应用层向下开始,一层一层包装,到了物理层,两个物理层之间相互连接,
再从第二列物理层开始一层一层往上开始拆包装。
每层运行常见物理设备
传输层 ----》四层交换机、四层的路由器
网络层 -----》路由器、三层交换层
数据链路层 -----》网桥、以太网交换机、网卡
物理层 ------》中继器、集线器、双绞线
每层运行常见的协议
应用层------》自己写的代码
传输层------》tcp与udp协议
网络层------》ip协议
数据链路层----》arp协议
物理层------》 网卡 网线等等
基于tcp协议的socket
socket套接字
理解socket
socket是应用层与tcp/ip协议族通信的中间软件抽象层,它是一组接口。
在设计模式中,socket其实就是一个门面模式,它把复杂的tcp/ip协议族隐藏在
socket接口后面,对用户来说,一组简单的接口就是全部,让socket去组织数据,
以符合指定的协议。
站在我的角度看socket:
其实socket就是一个模块。我们通过调用模块中已经实现的方法建立两个进程之间
的连接和通信。
也有人将socket说成ip+port(端口),因为ip是用来标识互联网中的一台
主机的位置,而port是用来标识这台机器上的一个应用程序。
所以我们只要确立了ip和port就能找到一个应用程序,并且使用socket模块与之通信。
socket套接字
基于文件类型的套接字家族
套接字家族的名字:AF_UNIX
Unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,
两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信。
基于网络类型的套接字家族
套接字家族的名字:AF_INET
(还有AF_INET6被用于ipv6,还有一些其他的地址家族,不过,他们要么是只用于某个平台,
要么就是已经被废弃,或者是很少被使用,或者根本没有实现,所有地址家族中,AF_INET是
使用最广泛的一个,python支持很多种地址家族,但由于我们只关心网络编程,
所以大部分时候我们只使用AF_INET)
基于tcp协议的socket代码
1 #server 端
2 # import socket
3 # sk = socket.socket() # 买手机
4 # sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # 写这
5 # 个是避免服务重启的时候报 address already in use 这个错
6 # # sk.bind(("ip","port")) # 接受的是一个元祖,里面是ip与port
7 # sk.bind(("127.0.0.1",8080)) # 绑定手机卡
8 # sk.listen() # 监听
9 #
10 # conn,addr = sk.accept() # 接收到别人的电话 connection 连接
11 # address 地址 是别人的地址
12 #
13 # ret = conn.recv(1024) # 听别人说话
14 # print(ret)
15 # conn.send(b"hello") # 和别人说话 ,必须传一个bytes类型
16 #
17 # conn.close() # 挂电话
18 #
19 # sk.close() # 关手机
20 # ===================================================
21
22 import socket
23 sk = socket.socket() # 买手机
24 sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
25 # 写这个是避免服务重启的时候报 address already in use 这个错
26 # sk.bind(("ip","port")) # 接受的是一个元祖,里面是ip与port
27 sk.bind(("127.0.0.1",8080)) # 绑定手机卡
28 sk.listen() # 监听
29
30 conn,addr = sk.accept() # 接收到别人的电话 connection 连接
31 # address 地址 是别人的地址
32 print(addr)
33 while True:
34 ret = conn.recv(1024).decode("utf-8")
35 if ret == "bye":
36 break
37 print(ret)
38 info = input(">>>")
39 conn.send(bytes(info,encoding="utf-8"))
40 # ret = conn.recv(1024) # 听别人说话
41 # print(ret)
42 # conn.send(b"hello") # 和别人说话 ,必须传一个bytes类型
43 # ret = conn.recv(1024)
44 # print(ret.decode("utf-8"))
45 # conn.send(bytes("大碗油泼面加蛋",encoding="utf-8"))
46 conn.close() # 挂电话
47 sk.close() # 关手机
1 # client端
2
3 # import socket
4 # sk = socket.socket() # 买手机
5 # sk.connect(("127.0.0.1",8080)) # 拨别人的号
6 #
7 # sk.send(b"python")
8 # ret = sk.recv(1024)
9 # print(ret)
10 #
11 # sk.close()
12 # =======================================================
13
14 import socket
15 sk = socket.socket() # 买手机
16 sk.connect(("127.0.0.1",8080)) # 拨别人的号
17 while True:
18 info = input(">>>")
19 sk.send(bytes(info,encoding="utf-8"))
20 ret = sk.recv(1024).decode("utf-8")
21 print(ret)
22 if ret == "bye":
23 sk.send(b"bye")
24 break
25
26 # sk.send(b"python")
27 # ret = sk.recv(1024)
28 # print(ret)
29 # sk.send(bytes("中午吃什么?",encoding="utf-8"))
30 # ret = sk.recv(1024)
31 # print(ret.decode("utf-8"))
32 sk.close()
注:本文是根据老男孩课程内容整理而成的,本文仅供个人笔记使用,如果有侵犯,请联系我,我立即撤销。