首页 > 技术文章 > 网络编程

Hedger-Lee 2020-03-08 23:39 原文

网络编程

1.网络概念的引入

  • 两个运行中的程序如何传递信息?
    • 通过文件
  • 两台机器上的两个运行中的程序如何通信?
    • 通过网络

2.网络开发架构

  • B/S架构 网页开发
    • browser 浏览器
    • server 服务端
  • C/S架构 ftp
    • client 客户端
    • server 服务端
  • 开发趋势:统一程序的入口
  • 两者关系:B/S架构是特殊的C/S架构

3.网络访问

3.1网络地址

  • ip 地址:确认一台机器
    • 公网ip
      • 这个ip地址能被所有人访问到,是申请得到的
    • 内网ip
      • 指定分配的,一般有
        • 192.168.0.0 - 192.168.255.255
        • 172.16.0.0 - 172.31.255.255
        • 10.0.0.0 - 10.255.255.255
    • 网关ip
      • 一个局域网的网络出口,访问局域网之外的区域都需要经过路由器和网关
  • 网段:指的是一个地址段 x.x.x.0 x.x.0.0 x.0.0.0
  • 子网掩码:判断两台机器是否在同一个网段内的
  • port 端口
    • 0-65535
  • ip + port 确认一台机器上的一个应用

3.2设备

  • 网卡 :是一个实际存在在计算机中的硬件
    • mac地址 :每一块网卡上都有一个全球唯一的mac地址
  • 交换机 :是连接多台机器并帮助通讯的物理设备,只认识mac地址
    • 完成局域网内的多台机器之间的通信
    • 单播,组播,广播
  • 路由器:完成局域网与局域网之间的联系
    • 能识别ip地址

4.协议

  • 两台物理设备之间对于要发送的内容,长度,顺序的一些约定

4.1arp协议

  • 由交换机实现的,是一个地址解析协议
  • 通过ip地址获取一台机器的mac地址
  • 通过广播,单播实现

4.2ip协议

  • ipv4协议 4位的点分十进制 32位2进制表示
    • 0.0.0.0 - 255.255.255.255
  • ipv6协议 6位的冒分十六进制 128位2进制表示
    • 0:0:0:0:0:0-FFFF:FFFF:FFFF:FFFF:FFFF:FFFF

4.3tcp/udp协议

4.3.1tcp协议

  • 特点:面向连接的,可靠的,流式的,全双工通信,传递长度没有限制

  • 三次握手

    • client端向server端:发送 请求连接 请求(syn)

    • server端向client端:通过接收到的 请求连接 请求(ack)

      ​ 并且向client端发送 请求连接 请求(syn)

    • client端向server端:通过接收到的 请求连接 请求(ack)

  • 四次挥手

    • client端向server端:发送 断开连接 请求(fin)
    • server端向client端:通过接收到的 断开连接 请求(ack)
    • server端向client端:向client端发送 断开连接 请求(fin)
    • client端向server端:通过接收到的 断开连接 请求(ack)
  • 在建立连接后,每发送一条信息都会有回执

  • 为了保证数据的完整性,会有重传机制

  • 长连接:会一直占用双方的端口

  • 应用场景:文件的上传和下载

  • 拆包机制,传输是先拆包再合包进行传输的

    • 由于拆包机制会出现粘包现象

4.3.2udp协议

  • 特点:面向数据报的,无连接的,不可靠的
  • 能完成一对一,一对多,多对一,多对多的高效通讯协议
  • 可能会丢消息
  • 能够传递的数据的长度是有限的,跟数据传递设备的设置有关系
  • 应用场景:即时通讯
  • sk = socket.socket(type=socket.SOCK_DGRAM)

4.4自定义协议

  • 自定义协议1
    • 首先发送报头
      • 报头长度为4个字节
      • 内容是即将发送的报文的字节长度
      • 使用struct模块
    • 再发送报文
  • 自定义协议2
    • 专门用来做文件发送的协议
      • 先发送报头字典的长度
      • 再发送字典(字典中包含文件的名字,大小····)
      • 再发送文件的内容

5.粘包现象

  • 本质:接收信息的边界不清晰
  • 在接收端的粘包
    • 由于tcp协议中所传输的数据无边界,接收端来不及接收的多条数据会在接收端的内核的缓存端黏在一起
  • 在发送端的粘包
    • 由于两个数据的发送时间间隔短+数据的长度小,为了减少tcp协议中的“确认收到”的网络延迟时间,所以由tcp协议的优化机制将两条信息作为一条信息发送出去了
  • 解决方法:使用自定义协议,核心借用struct模块

6.osi七层模型

6.1.七层模型

  • 应用层
  • 表示层
  • 会话层
  • 传输层
  • 网络层
  • 数据链路层
  • 物理层

6.2osi五层协议

  • 应用层 python代码
    • http https ftp smtp协议
  • 传输层 端口/服务相关
    • tcp/udp协议 端口 四层交换机,四层路由器
  • 网络层 ip相关
    • ipv4/ipv6协议 路由器,三层交换机
  • 数据链路层 mac相关
    • arp协议 网卡,交换机
  • 物理层

7. I/O操作

  • 输入输出都是相对内存来讲的
    • input 输入到内存 recv recvfrom
    • output 从内存输出 send sendto

8.阻塞和非阻塞

  • 阻塞:cpu不工作,如accept

  • 非阻塞:cpu工作

  • 几种模型

    • 阻塞io模型
    • 非阻塞io模型
    • 事件驱动io
    • io多路复用
    • 异步io模型

9.代码编写

9.1 socket模块

  • 又称套接字

  • 工作在应用层和传输层之间的抽象层,帮助我们完成所有信息的组织和拼接

  • 对于程序员来说,已经是网络操作的底层

  • socket历史

    • 同一台机器上的两个服务之间的通信
      • 基于文件操作来完成的
    • 基于网络的多台机器之间的多个服务通信
  • 基本模板

    ######## server端 ########
    import socket
    
    sk = socket.socket()
    sk.bind(('127.0.0.1', 9000))
    sk.listen()
    conn, addr = sk.accept()
    # 中间为要进行的操作
    conn.close()
    sk.close()
    
    ######## client端 ########
    import socket
    
    sk = socket.socket()
    sk.connect(('127.0.0.1', 9000))
    # 中间为要进行的操作
    sk.close()
    

9.2 struct模块

  • struct.pack 将一个数字转换为四个字节的bytes类型

    import struct
    
    bytes_len = struct.pack('i', 10000)
    # 将10000转为一个4个字节的bytes类型
    
  • struct.unpack 将一个四个字节的bytes类型转换回数字,结果是一个元组

    import struct
    
    length = struct.unpack('i', bytes_len)
    # 将一个4个字节的bytes类型转回其原本的数字
    

9.3 hamc模块

  • 校验客户端的合法性

  • hamc.new(盐,要加密的内容)

    import hamc
    
    h = hmac.new(secret_key, randseq)
    res = h.digest()
    

9.4 socketserver模块

  • 实现一个同时连接多个

  • 基本模板

    import socketserver
    
    class Myserver(socketserver.BaseRequestHandler):
        def handle(self):  # 自动触发了handle方法,并且self.request == conn
            要进行的操作
    
    server = socketserver.ThreadingTCPServer(('127.0.0.1',9000),Myserver)
    server.serve_forever()
    

推荐阅读