Python学习笔记(十九):

  1. Socket
  2. 粘包情况处理
  3. 模拟上传文件

1. Socket

  • 服务器端Socket建立
import socket

sk = socket.socket()
print(sk)   # <socket.socket fd=448, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0>

# 绑定端口
address = ('127.0.0.1', 8000)
sk.bind(address)
# 排队人数
sk.listen(3)

print('waiting...')
conn = sk.accept()
print(conn)
  • 客户端链接s
import socket

sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.connect(address)
  • server下的方法
  1. bind()# 绑定端口
  2. listen()# 设置监听数
  3. accept()#
  4. recv()# 接收信息
  5. send()# 发送信息 必须为byte类型
  6. sendall()# 发送长信息
  7. close()# conn.close() 终止通话 sk.close()关闭端口
  • client下的方法
  1. connetc()# 连接
  2. recv()# 接收信息
  3. send()# 发送信息 必须为byte类型
  4. sendall()# 发送长信息
  5. close()#终止通话
  • 注意,在数据传输的过程中用的是client端的sk而非server端的sk

2. 粘包问题处理

# 在发送端添加一个recv
# 在接收端添加一个send

3. 模拟上传文件

  • 流程
  1. 建立链接
  2. 客户端选择上传文件
  3. 服务端接收上传文件
  • 客户端代码示例:
import socket, os

sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.connect(address)
# 获取文件夹路径
BASE_DIR = os.path.dirname(os.path.abspath(__file__))

while True:
    # 输入上传方式和要上传的文件名
    inp = input('>>:').strip()
    # 分离命令和路径
    cmd, path = inp.split('|')
    # 路径拼接
    path = os.path.join(BASE_DIR, path)
    # 分别提取文件名,文件大小,文件信息
    file_name = os.path.basename(path)
    file_size = os.stat(path).st_size
    file_info = 'post|%s|%s' % (file_name, file_size)
    # 以固定格式发送文件信息
    sk.sendall(bytes(file_info, 'utf8'))

    # 读取要发送的文件的信息
    f = open(path, 'rb')
    # 已经发送的数据大小
    has_sent = 0
    while has_sent != file_size:
        # 使用f.read提取信息
        data = f.read(1024)
        sk.sendall(data)
        has_sent += len(data)

    f.close()
    print('上传成功')
  • 服务端代码示例:
import socket, os

sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.bind(address)
sk.listen(3)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))

while 1:
    conn, addr = sk.accept()
    while 1:
        # 接收文件信息
        data = conn.recv(1024)
        # 以固定格式分离文件信息
        cmd, file_name, file_size = str(data, 'utf8').split('|')
        path = os.path.join(BASE_DIR, 'yuan', file_name)
        file_size = int(file_size)
        # 上传文件到指定位置
        f = open(path, 'ab')
        # 已经接收的文件大小
        has_receive = 0
        while has_receive != file_size:
            data = conn.recv(1024)
            f.write(data)
            has_receive += len(data)
        f.close()