一、网络基础
网络建立的目的是为了数据交互(通信)
如何实现通信:
1.建立好底层的物理连接介质
2.有一套统一的通信标准,称之为互联网协议
1、osi七层协议
互联网协议按照功能的不同分为osi七层或tcp/ip五层或tcp/ip四层
每层运行的常见物理设备:
2、tcp/ip五层协议模型讲解
2.1物理层:主要是基于电器特性发送高低电压(电信号),高电压对应数字1,低电压对应数字0
2.2数据链路层:定义了电信号的分组方式,由于单纯的0和1并没有任何意义,必须规定电信号多少位一组,每组什么意思
以太网协议:
早期每个公司都有自己的分组方式,后来形成统一的标准,即以太网协议Ethernet
Ethernet规定
1.一组电信号构成一个数据包,叫做‘帧’,每一数据帧分成:报头head和数据data两部分
2.报头(head):固定字节数,里面包含发送者,接收者,数据类型。数据(data):数据包的具体内容
mac地址
head中包含的源和目标地址的由来:以太网规定接入internet的设备都必须具备网卡,发送地址和接收地址都是通过网卡来的
每块网卡出厂时都被烧制上一个唯一的mac地址,前6位是厂商编号,后6位是流水线号
广播:
有了mac地址,同一网络内的两台计算机就可以通信了
2.3网络层:不同网络内想要通信,光靠Ethernet、mac地址和广播并不可行,所以引入一套新的地址用来区分不同的网络,这套地址就叫网络地址
ip协议:
规定网络地址的协议叫ip协议,它定义的地址称为ip地址,广泛采用v4版本即ipv4,它规定网络地址由32位2进制表示
范围为0.0.0.0 ---255.255.255.255
ip地址分为两部分
网络部分:标识子网
主机部分:标识主机
子网掩码:
形式上等同于ip地址,也是32位二进制,网络部分全部为1,主机部分全为0。
知道子网掩码我们就能判断,任意两个ip地址是否处在同一个子网络。方法是将两个ip地址分别进行AND运算(两个都为1运算结果为1,否则为0),比较结果是否相同,如果相同的话就表明他们是在一个子网络中,否则就不是
总结ip协议的作用:1.为每台计算机分配ip地址,2确定这些地址是不是在同一个子网络中。
ARP协议
广播的方式发送数据包,获取目标主机的mac地址
2.4传输层:网络层的ip帮我们区分子网,以太网层的mac帮我们找到主机,传输层建立端口到端口的通信,端口就是应用程序与网关关联的编号 端口范围0-65535, 0-1023位系统占用端口
tcp协议:可靠传输,tcp数据包没有长度限制,必须等到有回应才会继续发送
udp协议:不可靠传输,不管有没有收到响应只管发送
tcp的三次握手
2.5应用层:规定应用程序的数据格式
二、socket介绍
socket是应用层与tcp/ip协议通信的中间软件抽象层,它是一组接口,它吧复杂的TCP/IP协议隐藏在socket接口后面。
基于文件类型的套接字家族:
套接字家族的名字:AF_UNIX
unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运 行在同一机器,可以通过访问同一个文件系统间接完成通信
基于网络类型的套接字家族:
套接字家族的名字:AF_INET
AF_INET被用于ipv4,AF_INET6被用于ipv6
三、套接字使用
import socket socket.socket(socket_family,socket_type,protocal=0) socket_family 可以是 AF_UNIX 或 AF_INET。socket_type 可以是 SOCK_STREAM 或 SOCK_DGRAM。protocol 一般不填,默认值为 0。 获取tcp/ip套接字 tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 获取udp/ip套接字 udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 由于 socket 模块中有太多的属性。我们在这里破例使用了'from module import *'语句。使用 'from socket import *',我们就把 socket 模块里的所有属性都带到我们的命名空间里了,这样能 大幅减短我们的代码。 例如tcpSock = socket(AF_INET, SOCK_STREAM)
客户端套接字函数
s.connect() 主动初始化TCP服务器连接
s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
面向文件的套接字的函数
s.fileno() 套接字的文件描述符
s.makefile() 创建一个与该套接字相关的文件
面向锁的套接字方法
s.setblocking() 设置套接字的阻塞与非阻塞模式
s.settimeout() 设置阻塞套接字操作的超时时间
s.gettimeout() 得到阻塞套接字操作的超时时间
基于tcp协议通信的套接字(简单版本)
服务端:
from socket import socket, AF_INET, SOCK_STREAM # socket 套接字 # AF_INET IPv4 # SOCK_STREAM socket流 IP = "127.0.0.1" PORT = 8888 ADDRESS = (IP, PORT) BUFSIZE = 1024 print("服务器开启了") # 1.创建服务器socket对象 serSocket = socket(AF_INET, SOCK_STREAM) # 2.设置服务器地址 serSocket.bind(ADDRESS) # 3.设置连接管理队列 serSocket.listen(5) # 4.建立客户端服务器连接 cliSocket, addr = serSocket.accept() print(cliSocket) print(addr) # 5.收发数据 data = cliSocket.recv(BUFSIZE) print(data.decode("utf-8")) cliSocket.send("服务器返回的数据".encode("utf-8")) # 6.断开客户端 cliSocket.close() # 7.关闭服务器 serSocket.close() print("服务器关闭了") server
客户端:
from socket import socket, AF_INET, SOCK_STREAM IP = "127.0.0.1" PORT = 8888 ADDRESS = (IP, PORT) BUFSIZE = 1024 print("客户端开启了") # 1.创建客户端socket对象 cliSocket = socket(AF_INET, SOCK_STREAM) # 2.连接服务器地址 cliSocket.connect(ADDRESS) print(cliSocket) # 3.收发数据 cliSocket.send("客户端发送的数据".encode("utf-8")) data = cliSocket.recv(BUFSIZE) print(data.decode("utf-8")) # 4.关闭客户端 cliSocket.close() print("客户端关闭了") client