python 语法 网络编程

1.网络编程相关概述

  • 概述
    网络编程也叫套接字编程,Socket编程就是用来实现 网络互联的 不同计算机上 运行的程序间 可以进行数据交互.

  • 三要素:

    • IP地址:设备在网络中唯一标识

    • 端口号:程序在设备上的唯一标识

    • 协议:通信传输规则​

  • IP地址详解:

    • 概述:
      设备(电脑, 手机, IPad, 耳机…)在网络中的唯一标识.
  • 常用的IP地址分类:

    • 按照 代数 划分:
      IPv4: 4字节, 十进制来表示, 例如: 192.168.13.157
      IPv6: 8字节, 十六进制来表示, 理论上来讲, 可以让地球上的每一粒沙子都有自己的IP.
    • 按照 Ipv4 常用类别划分:
      城域网: 第1段是网络地址 + 后3段是主机地址, 例如: 10.0.0.0
      广域网: 前2段是网络地址 + 后2段是主机地址, 例如: 10.21.0.0
      局域网: 前3段是网络地址 + 后1段是主机地址, 例如: 192.168.13.*
  • 两个和IP相关的命令:
    查看本机的IP: Win + r 输入cmd调出界面在输入
    ipconfig 适用于 windows系统
    ifconfig 适用于 linux系统, Mac系统

  • 测试网络连接是否通畅:
    ping 主机地址 或者 域名

  • 端口号:

    • 端口: 传输数据的通道, 每个程序都有. 类似于: 每个教室都有自己的门.
    • 端口号: 程序在设备上的唯一标识.
    • 范围: 0 ~ 65535, 其中0 ~ 1023已经被系统占用或者用作保留端口, 你自己在使用的时候, 尽量规避这个号段.
  • 协议:
    全称叫: Transmission Control Protocol, 简称叫: 传输控制协议, 即: TCP.

  • 作用: 通信双方都要遵循的 通信规则.

    • 常用的协议及其特点:
    • UDP: # 类似于: 群聊
      1. 面向无连接.
      2. 采用 数据包 的方式传输数据, 有大小限制(每个包不超过64KB).
      3. 不安全(不可靠)协议.
      4. 效率相对较高.
      5. 不区分客户端 和 服务器端, 叫: 发送端和接收端.
    • TCP: # 类似于: 打电话
      1. 面向有连接的.
      2. 采用 流的方式传输数据, 理论上无大小限制.
      3. 安全(可靠)协议.
      4. 效率相对较低.
      5. 区分客户端 和 服务器端.

1.1 三次握手 和 四次挥手?

  • 三次握手:
      1. 客户端像服务器端发出请求, 申请建立连接.
      1. 服务器端校验客户端数据合法后, 给出客户端回执信息, 可以建立连接.
      1. 客户端重新向服务器端发出请求, 建立连接.
  • 四次挥手:
    • 因为TCP协议是双向的, 需要两个方向都断开.

2.socket对象初始

  • 网络通信原理:
    网络通信也叫套接字通信, Socket通信, 即: 通信双方都有自己的Socket对象, 数据在两个Socket之间通过 数据报包 或者 流的方式传输数据.

  • 创建步骤:

      1. 导包.
      1. 创建Socket对象.
      1. 打印socket对象.
# 1. 导包.
import socket

# 2. 创建对象.
# object: 对象的意思
# 参1: Address Family: 地址族, 指定IP地址的协议, IPV4, IPV6, UNIX...
# 参2: Socket Type: 指定套接字的类型, TCP, UDP, UNIX...
# 这里的: socket.AF_INET: 指的是IpV4,  socket.SOCK_STREAM: 指的是 字节流的方式.
socket_obj = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 3. 打印对象.
print(socket_obj)

3.Socket 创建步骤

3.1 服务器端

  • 步骤:

    • 导包

    • 1.创建服务器端对象

    • 2.绑定地址值和端口号

    • 3.设置监听数量

    • 4.等待客户端申请建立连接, 如果有客户端申请建立连接, 校验数据合法后, 会返回1个: (负责和该客户端交互的socket对象, 客户端的信息) 元组

    • 5.给客户端发送数据 字节形式

    • 6.接受客户端数据 字节形式

    • 7.释放资源

代码演示

'''也使用
127.0.0.1   本地回路(回环)地址, 即: 在哪台计算机上运行, 就代表哪台电脑. 简单理解: 代表本机.
也可使用 本机地址
'''
 导包.
import socket

# 在main中编写.
if __name__ == '__main__':
    # 1. 创建服务器端Socket对象, 指定: 地址族, 传输类型.
    # 参1: IPV4,  参2: 字节流
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 2. 绑定地址和端口.
    # server_socket.bind(("127.0.0.1", 2121))
    server_socket.bind(("192.168.13.157", 2121))
    # 3. 设置监听数量.    范围: 1 ~ 128
    server_socket.listen(5)
    # 4. 等待客户端连接, 如有连接, 则返回: (和客户端交互的Socket对象, 客户端地址)
    print('等待客户端连接中.....')
    # print('Server 1')
    accept_socket, client_info = server_socket.accept()
    # print('Server 2')
    # 5. 给客户端发送数据.
    # accept_socket.send('Welcome to study socket!'.encode('utf-8'))
    accept_socket.send(b'Welcome to study socket!')

    # 6. 接受客户端发送的数据并打印.
    recv_data_bys = accept_socket.recv(1024)        # receive: 接收,  一次读取1024个字节
    # 把字节转成字符串, 并打印.
    recv_data = recv_data_bys.decode('utf-8')
    print(f'服务器端收到 {client_info} 发送的信息: {recv_data}')

    # 7. 关闭Socket对象.
    accept_socket.close()       # 一般只关闭 和客户端交互的socket对象.
    # server_socket.close()     # 服务器端socket对象一般不关闭.



3.2 客户端

  • 步骤

    • 导包

    • 1.创建客户端对象

    • 2.连接服务器地址和端口号

    • 3.接受服务器端数据并打印

    • 4.发送数据到服务器端

    • 5.释放资源

代码演示

"""
import socket

# 在main中测试.
if __name__ == '__main__':
    # 1. 创建客户端Socket对象, 指定: 地址族, 传输类型.
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 2. 连接(服务器端)地址和端口.
    # client_socket.connect(("127.0.0.1", 2121))
    client_socket.connect(("192.168.13.157", 2121))
    # 3. 接受服务器端发送的数据并打印.
    # 分解版
    # recv_data_bys = client_socket.recv(1024)
    # recv_data = recv_data_bys.decode("utf-8")
    # 合并版
    recv_data = client_socket.recv(1024).decode("utf-8")
    print(f'客户端收到: {recv_data}')
    # 4. 给服务器端发送数据(回执信息).
    client_socket.send('有内鬼, 终止交易! Over'.encode("utf-8"))
    # 5. 关闭Socket对象.
    client_socket.close()

4.端口号复用

  • 解释:
      1. 127.0.0.1 本地回路(回环)地址, 即: 在哪台计算机上运行, 就代表哪台电脑. 简单理解: 代表本机.
      1. 当服务器端关闭的时候, 端口号释放可能需要1 ~ 2分钟的时间, 如果此时再次开启服务器端, 可能会报: 端占用的错误.
  • 解决方案如下:
      1. 重新手动更换1个端口号.
      1. 设置端口号重用(复用).

代码演示

# 导包.
import socket

# 在main中编写.
if __name__ == '__main__':
    # 1. 创建服务器端Socket对象, 指定: 地址族, 传输类型.
    # 参1: IPV4,  参2: 字节流
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 2. 绑定地址和端口.
    # server_socket.bind(("127.0.0.1", 2121))
    server_socket.bind(("192.168.13.157", 2121))
    # 3. 设置监听数量.    范围: 1 ~ 128
    server_socket.listen(5)
    # 4. 等待客户端连接, 如有连接, 则返回: (和客户端交互的Socket对象, 客户端地址)
    print('等待客户端连接中.....')
    # print('Server 1')
    accept_socket, client_info = server_socket.accept()
    # print('Server 2')
    # 5. 给客户端发送数据.
    # accept_socket.send('Welcome to study socket!'.encode('utf-8'))
    accept_socket.send(b'Welcome to study socket!')

    # 6. 接受客户端发送的数据并打印.
    recv_data_bys = accept_socket.recv(1024)        # receive: 接收,  一次读取1024个字节
    # 把字节转成字符串, 并打印.
    recv_data = recv_data_bys.decode('utf-8')
    print(f'服务器端收到 {client_info} 发送的信息: {recv_data}')

    # 7. 关闭Socket对象.
    accept_socket.close()       # 一般只关闭 和客户端交互的socket对象.
    # server_socket.close()     # 服务器端socket对象一般不关闭.

    # 8. 设置端口号复用.
    # 参1: 当前的套接字对象.
    # 参2: 参数名, 即: 设置端口号复用.
    # 参3: 参数的值, True: 启用
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

5.长连接

  • 长连接解释:
    即: 客户端和服务器端成功连接后, 可以一直收发数据, 而不用频繁的创建和销毁Socket对象.
    可以选择合适的时机, 销毁Socket对象.

5.1接受服务器端

代码演示

import socket

if __name__ == '__main__':
    # 1. 创建服务器端Socket对象.
    ser_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 2. 绑定服务器端ip 和 端口号.
    ser_socket.bind(("192.168.13.27", 6666))
    # 3. 设置监听连接数.
    ser_socket.listen(5)
    # 4. 启动监听, 等待客户端建立连接.
    accept_socket, client_info = ser_socket.accept()

    # 5. 接收客户端发送的信息.
    while True:
        # 5.1 接收客户端发送的信息(二进制形式 => 字符串)
        recv_data = accept_socket.recv(1024).decode("utf-8")
        # 5.2 打印接收到的客户端的消息.
        print(f'服务器端收到: {recv_data}')
        # 5.3 判断客户端是否发送了"996", 如果是, 结束程序.
        if recv_data == "996":
            break

    # 6. 释放资源.
    accept_socket.close()

5.2客户端

代码演示

import socket

if __name__ == '__main__':
    # 1. 创建客户端Socket对象.
    cli_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 2. 连接服务器端. ip 和 端口号
    cli_socket.connect(("192.168.13.27", 6666))

    # 3. 发送数据到服务器端.
    while True:
        # 3.1 提示用户录入要发送的数据, 并接收.
        data = input('请录入要发送的数据: ')
        # 3.2 将其转成二进制形式, 发送给服务器端.
        cli_socket.send(data.encode("utf-8"))
        # 3.3 判断用户是否要退出.
        if data == "996":
            break

    # 4. 释放资源.
    cli_socket.close()

6.扩展-文件上传

6.1 文件或者图片上传-客户端

代码展示

import socket

if __name__ == '__main__':
    # 1. 创建客户端Socket对象.
    cli_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 2. 连接服务器端. ip 和 端口号
    # cli_socket.connect(("127.0.0.1", 8888))
    cli_socket.connect(("192.168.13.157", 8888))
    # 3. 读取数据源文件的信息, 并发送数据到服务器端.
    # with open('d:/绕口令.txt', 'rb') as src_f:
    with open('d:/图片/a.jpg', 'rb') as src_f:
        # 扩展: 你也可以考虑先把文件名发给服务器端, 然后再上传文件.
        # cli_socket.send('绕口令.txt'.encode('utf-8'))

        # 3.1 分批次读取, 一次读取 1024个字节.
        while True:
            # 3.2 具体的从文件中读取数据的动作.
            data = src_f.read(1024)
            # 3.3 将读取到的数据写给 => 服务器端.
            cli_socket.send(data)
            # 3.4 判断是否读取完毕.
            if len(data) <= 0:
                break
    # 5. 释放资源.
    cli_socket.close()

6.2 文件或者图片上传-服务器端

代码展示

import socket

if __name__ == '__main__':
    # 1. 创建服务器端Socket对象.
    ser_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 2. 绑定服务器端ip 和 端口号.
    ser_socket.bind(("127.0.0.1", 8888))
    # 3. 设置监听连接数.
    ser_socket.listen(10)
    # 4. 启动监听, 等待客户端建立连接.
    accept_socket, client_info = ser_socket.accept()

    # 5. 接收客户端的回执信息.
    # 5.1 关联目的地文件, 用于把客户端的数据写到该文件中.
    with open('./data/文件.txt', 'wb') as dest_f:
        # 5.2 循环接收客户端写过来的文件数据.
        while True:
            # 5.3 具体的接收客户端数据的动作.
            recv_data = accept_socket.recv(1024)
            # 5.4 判断读取到的数据是否为空, 为空, 说明文件传输完毕.
            if len(recv_data) <= 0:
                break
            # 5.5 把读取到的数据写入到目的地文件中.
            dest_f.write(recv_data)

    # 7. 释放资源.
    accept_socket.close()

6.3支持多个客户端发送多个文件

代码演示

import socket

if __name__ == '__main__':
    # 1. 创建服务器端Socket对象.
    ser_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 2. 绑定服务器端ip 和 端口号.
    ser_socket.bind(("192.168.13.157", 8888))
    # 3. 设置监听连接数.
    ser_socket.listen(10)

    try:
        count = 0  # 计数变量.
        while True:
            count += 1  # 走到这里, 说明是1个新文件.
            # 拼接文件名,我做主想取什么名字就什么名
            file_name = './data/文件_' + str(count) + '.jpg'
            # 4. 启动监听, 等待客户端建立连接.
            accept_socket, client_info = ser_socket.accept()
            # 5. 接收客户端的回执信息.
            # 5.1 关联目的地文件, 用于把客户端的数据写到该文件中.
            with open(file_name, 'wb') as dest_f:
                # 5.2 循环接收客户端写过来的文件数据.
                while True:
                    # 5.3 具体的接收客户端数据的动作.
                    recv_data = accept_socket.recv(8192)
                    # 5.4 判断读取到的数据是否为空, 为空, 说明文件传输完毕.
                    if len(recv_data) <= 0:
                        break
                    # 5.5 把读取到的数据写入到目的地文件中.
                    dest_f.write(recv_data)
            # 走到这里, 说明文件传输完毕.
            print(f'服务器端收到 {client_info} 上传文件成功!')
            # 7. 释放资源.
            accept_socket.close()
    except:
        pass

总结

可以和好朋友试试哦,有什么悄悄话直接发给他,持续更新中~~~

  • 19
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值