网络编程

相关概念

  • OSI 七层模型:开放系统互联参考模型
  • TCP/IP:在 OSI 七层模型的基础上进行简化抽象出来的广泛使用的网络协议簇
  • TCP:传输控制协议
    • 有链接的、数据是安全的(有保障)
    • 传输的速度相对较慢,三次握手、四次挥手、数据检查
  • UDP:用户数据报协议
    • 无连接的,数据不可靠的
    • 传输速度相对较快
  • IP 地址:在局域网中唯一的标识一台计算机
    • 查看:
      • Windows:ipconfig
      • 类 Unix:ifconfig
    • 检查:用于检查网络的连通性
      • ping:IP / 域名
    • 端口:每个应用都有唯一的端口号,在一个系统中是不能重复的
      • 范围:0~65535
      • 系统:0~1024,已经被常用的服务占用了
        • http:80
        • https:443
        • ftp:21
        • ssh:22
        • smtp:25
        • MySQL:3306
        • Redis:6379
        • MongoDB:27017
    • 网络编程特性:
      • IP + 端口
      • 库:socket

TCP 协议

  • 说明:

    • 面向连接
    • 数据可靠(丢失重复)
    • 传输速度慢
    • 三次握手、四次挥手
  • 过程:

  • 简单使用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    import socket

    """
    服务端:接受客户端的请求
    客户端:与服务器建立连接,然后进行通信
    """

    # 创建套接字
    # 参数1:协议族,socket.AF_INET表示IPV4协议族
    # 参数2:传输协议,socket.SOCK_STREAM表示TCP
    skt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 与服务器建立连接
    # 参数是一个元组:格式是(主机/域名, 端口)
    skt.connect(('www.baidu.com', 80))

    # 向服务器发送请求
    skt.send(b'GET / HTTP/1.1\r\nHOST: www.baidu.com\r\nConnection: close\r\n\r\n')

    # 接收服务器的数据
    data = []
    while True:
    temp = skt.recv(1024)
    if temp:
    data.append(temp)
    else:
    break

    # 关闭套接字
    skt.close()

    content = b''.join(data).decode('utf-8')
    # print(content)
    headers, body = content.split('\r\n\r\n', 1)
    # print(headers)
    print(body)
  • TCP 的客户端与服务器:

    • 服务器:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      import socket

      if __name__ == "__main__":
      # 创建套接字
      skt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      # 绑定主机和端口
      skt.bind(('10.251.251.24', 8888))
      # 监听服务
      skt.listen()
      # 阻塞等待客户端的链接
      client_skt, client_addr = skt.accept()
      # print(client_skt)
      # print(client_addr)
      # 有客户端链接成功,会创建新的套接字进行通信
      while True:
      recv_data = client_skt.recv(1024)
      print('狗蛋:', recv_data.decode('utf-8'))
      # 客服端发什么就回复什么
      client_skt.send(recv_data)

      client_skt.close()
      skt.close()
    • 客户端:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      import socket

      if __name__ == "__main__":
      # 创建套接字
      skt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      # 链接指定的主机和端口
      skt.connect(('10.251.251.24', 8888))

      while True:
      data = input('>>>:')
      skt.send(data.encode('utf-8'))
      # 接收服务器返回的内容
      recv_data = skt.recv(1024)
      print('服务器:', recv_data.decode('utf-8'))

      skt.close()

UDP 协议

  • 说明:

    • 面向无连接
    • 数据不可靠
    • 传输速度快
    • 适用于对数据要求不严格的场景
  • 过程:

  • 简单使用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import socket

    # 创建UDP套接字,与TCP基本一样,使用协议:socket.SOCK_DGRAM
    skt = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # 版本号:数据包序列号:用户名:主机:命令:消息内容[:附加数据]
    data = '1:123456:Jerry:windows:32:大家好才是真的好'

    for i in range(1, 255):
    ip = '10.251.251.' + str(i)
    addr = (ip, 2425)
    skt.sendto(data.encode('gbk'), addr)

    skt.close()
  • UDP 的客户端与服务器:

    • 服务器:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      import socket

      # 创建UDP套接字
      skt = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
      # 绑定主机和端口
      skt.bind(('10.251.251.24', 9999))

      while 1:
      # 阻塞等待接收客户端的数据
      recv_data, client_addr = skt.recvfrom(1024)
      # 打印客户端发来的数据
      print(client_addr, recv_data.decode('utf-8'))
      # 收到什么就回复什么
      skt.sendto(recv_data, client_addr)

      skt.close()
    • 客户端:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      import socket

      skt = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

      while 1:
      # 从终端获取输入
      data = input('>>>:')
      # 发送获取数据
      skt.sendto(data.encode('utf-8'), ('10.251.251.24', 9999))
      # 获取服务器发来的数据,格式:(data, (host, port))
      recv_data, server_addr = skt.recvfrom(1024)
      print('服务器:', recv_data.decode('utf-8'))

      skt.close()