文章目录
- 一、一些基本概念
- 二、软件的开发架构(c/s架构和b/s架构)
- 三、OSI模型
- 四、socket套接字编程
- 1.socket编程过程
- 2.python中的socket编程
一、一些基本概念
来了解一些网络的基本概念
名词 | 解释 |
---|---|
IP(互联网协议地址)IP | 用来标识网络中的一个通信实体的地址。互联网之间的通信相当于快递收发,需要知道每个电脑的详细地址才能实现数据的准确收发。2.广泛采用的v4版本即ipv4,它规定网络地址由32位2进制表示。范围: 0.0.0.0-255.255.255.255 |
子网 | 子网就是一个网中一个比较低级的网 |
子网掩码 | 子网掩码用来确定一个子网中的IP地址及数量,一个子网节点IP地址与子网掩码相与运算得到该子网下的IP地址。一般的子网掩码为255.255.255.0。通过子网掩码确定两个IP地址是否属于同一个子网。 |
网关 | 网络络关卡口的简称。他的作用就是:链接两个不同的网络,比如联通公司给你家装了宽带(相当于给你家装了一个网关),你家里的所有设备都是在一个局域子网中,这个局域网和互联网之间使用网关进行连接。 |
交换机 | 交换机的作用就是分发数据,为设备提供IP地址。交换机直接与设备的网卡连接,数据通过指定的端口发送到指定的设备上,交换机只关心与其联系的设备的mac地址。 |
路由器 | 路由器具备WAN口和多个LAN口。它实际上是**网关和交换机的结合体。**wan口与宽带公司机房相连,LAN口与局域网设备相连。 |
路由 | 数据从一台电脑发送到另一台电脑的时所走过的路线就叫做路由。 |
端口 | 同一台设备下有很多的应用程序,但是网卡只有一个,数据通过网卡获得和发送,如何确定接收的数据到底是哪一个程序的呢?发给QQ的数据不可能被微信接收。利用端口可以解决这个问题。 |
mac地址 | 每块网卡出厂时都被烧制上一个世界唯一的mac地址,长度为48位2进制,通常由12位16进制数表示(前六位是厂商编号,后六位是流水线号) |
局域网(Local Area Network,LAN) | 指在某一区域内由多台计算机互联成的计算机组。一般是方圆几千米以内。局域网可以实现文件管理、应用软件共享、打印机共享、工作组内的日程安排、电子邮件和传真通信服务等功能。局域网是封闭型的,可以由办公室内的两台计算机组成,也可以由一个公司内的上千台计算机组成。 |
二、软件的开发架构(c/s架构和b/s架构)
了解的涉及到两个程序之间通讯的应用大致可以分为两种:
- 应用类:qq、微信、网盘、优酷这一类是属于需要安装的桌面应用
- web类:比如百度、知乎、博客园等使用浏览器访问就可以直接使用的应用
这些应用的本质其实都是两个程序之间的通讯。而这两个分类又对应了两个软件开发的架构~
1.C/S架构
C/S架构:Client与Server ,中文意思:客户端与服务器端架构,这种架构也是从用户层面(也可以是物理层面)来划分的。
这里的客户端一般泛指客户端应用程序EXE,程序需要先安装后,才能运行在用户的电脑上,对用户的电脑操作系统环境依赖较大。
2.B/S架构
B/S架构:Browser与Server,中文意思:浏览器端与服务器端架构,这种架构是从用户层面来划分的。
浏览器其实也是一种Client客户端,只是这个客户端不需要大家去安装什么应用程序,只需在浏览器上通过HTTP请求服务器端相关的网页资源,客户端浏览器就能进行增删改查。
三、OSI模型
互联网的核心就是由一堆协议组成,协议就是标准。所有的计算机都学会了互联网协议,那所有的计算机都就可以按照统一的标准去收发信息从而完成通信了。人们按照分工不同把互联网协议从逻辑上划分了层级:
每一层都有自己的好多协议,这里有个神图,大概了解一下
这里我们重点看一下传输层的TCP和UDP:
TCP | UDP | |
---|---|---|
简介 | Transmission Control Protocol ,传输控制协议 | User Data Protocol ,用户数据报协议 |
优点 | 一个可靠的、面向连接的协议 | 传输效率高(发送前时延小),支持一对一、一对多、多对一、多对多、面向报文,尽最大努力服务,无拥塞控制 |
缺点 | 传输效率低、面向字节流 | 不可靠的、无连接的协议 |
应用 | Web浏览器;电子邮件、文件传输程序 | 域名系统 (DNS);视频流;IP语音(VoIP) |
TCP的三次握手
TCP是面向连接的协议,也就是说,在收发数据前,必须和对方建立可靠的连接。 而一个TCP 连接必须要经过三次 “ 对话 ” 才能建立起 来,其中的过程非常复杂,图示如下:
简单描述一下:
- 第一步,客户端发送一个包含SYN 即同步( Synchronize )标志的 TCP 报文, SYN 同步报文会指明客户端使用的端口以及TCP 连接的初始序号。
- 第二步,服务器在收到客户端的SYN 报文后,将返回一个 SYN+ACK 的报文,表示客户端的请求被接受,同时TCP 序号被加一, ACK 即确认( Acknowledgement )
- 第三步,客户端也返回一个确认报文ACK 给服务器端,同样 TCP 序列号被加一,到此一个 TCP 连接完成。然后才开始通信的第二步:数据处理。
TCP的四次挥手
断开链接也需要进行四次挥手操作,图示如下:
简单描述就是:
- 当主机A完成数据传输后,将控制位FIN置1,提出停止TCP 连接的请求 ;
- 主机B收到FIN后对其作出响应,确认这一方向上的TCP连接将关闭,将ACK置1;
- 由B 端再提出反方向的关闭请求, 将 FIN 置 1 ;
- 主机A对主机B 的请求进行确认,将 ACK 置 1 ,双方向的关闭结束 。
四、socket套接字编程
1.socket编程过程
Socket 是传输层供给应用层的编程接口,所以Socket 编程就分为 TCP 编程和 UDP 编程两类。
2.python中的socket编程
Python 中,我们用 socket() 函数来创建套接字。
服务器端套接字函数
函数 | 描述 |
---|---|
s.bind() | 绑定地址(host,port)到套接字, 在AF_INET下,以元组(host,port)的形式表示地址。 |
s.listen() | 开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。 |
s.accept() | 被动接受TCP客户端连接,(阻塞式)等待连接的到来 |
客户端套接字函数
函数 | 描述 |
---|---|
s.connect() | 主动初始化TCP服务器连接,。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。 |
s.connect_ex() | connect()函数的扩展版本,出错时返回出错码,而不是抛出异常 |
公共用途的套接字函数
函数 | 描述 |
---|---|
s.recv() | 接收TCP数据,数据以字符串形式返回,bufsize指定要接收的最大数据量。flag提供有关消息的其他信息,通常可以忽略。 |
s.send() | 发送TCP数据,将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。 |
s.sendall() | 完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。 |
s.recvfrom() | 接收UDP数据,与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。 |
s.sendto() | 发送UDP数据,将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。 |
s.close() | 关闭套接字 |
s.getpeername() | 返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。 |
s.getsockname() | 返回套接字自己的地址。通常是一个元组(ipaddr,port) |
s.setsockopt(level,optname,value) | 设置给定套接字选项的值。 |
s.getsockopt(level,optname[.buflen]) | 返回套接字选项的值。 |
s.settimeout(timeout) | 设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如connect()) |
s.gettimeout() | 返回当前超时期的值,单位是秒,如果没有设置超时期,则返回None。 |
s.fileno() | 返回套接字的文件描述符。 |
s.setblocking(flag) | 如果 flag 为 False,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)。非阻塞模式下,如果调用 recv() 没有发现任何数据,或 send() 调用无法立即发送数据,那么将引起 socket.error 异常。 |
s.makefile() | 创建一个与该套接字相关连的文件 |
我们来试验一下:
server.py
import socket
# 创建 socket 对象
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 获取本地主机名
host = socket.gethostname()
# 绑定端口号
serversocket.bind((host, 9999))
# 设置最大连接数,超过后排队
serversocket.listen(5)
while True:
# 建立客户端连接
clientsocket, addr = serversocket.accept()
print("连接地址: %s" % str(addr))
msg = '我是server.py文件' + "\r\n"
clientsocket.send(msg.encode('utf-8'))
clientsocket.close()
client.py
# 导入 socket、sys 模块
import socket
# 创建 socket 对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 获取本地主机名
host = socket.gethostname()
# 连接服务,指定主机和端口
s.connect((host, 9999))
# 接收小于 1024 字节的数据
msg = s.recv(1024)
s.close()
print(msg.decode('utf-8'))
运行这两个文件,会在client.py运行结果看到: