zoukankan      html  css  js  c++  java
  • python基础--socket套接字、粘包问题

    本地回环地址:127.0.0.1

    简易版服务端:

    import socket
    ​
    server = socket.socket()  # 就比如买了一个手机
    server.bind(("127.0.0.1",8080))  # bind中绑定的是IP地址和端口号,注意是一个元组,就比如,将手机卡,插入了手机
    server.listen(5)  # 半连接池,最大等待连接数为5个,就比如开机
    conn,address = server.accept()  # 接听电话等着别人给你打电话
    ​
    date = conn.recv(1024)  # 听别人说话,接收1023个字节数
    print(date)
    conn.send(b"hello")  # 给别人回话
    ​
    ​
    conn.close()  # 挂断电话
    server.close()  # 关机

    简易版客户端:

    import socket
    ​
    client = socket.socket()  #拿电话
    client.connect(("127.0.0.1",8080))  #绑定的是IP地址和端口号,也是一个元组 拨号
    ​
    client.send(b"hello")  # 对别人发消息
    ​
    date = client.recv(1024)  #接收别人说话,没次接收1024个字节
    print(date)
    ​
    client.close()  # 挂电话

    注意:在写服务端和客户端的时候send和recv需要一一对应,不能再两边都出现,recv是跟内存要数据,至于数据的来源无需考虑

    粘包:

    服务端:

    import socket
    ​
    server = socket.socket()  # 就比如买了一个手机
    server.bind(("127.0.0.1",8088))  # bind中绑定的是IP地址和端口号,注意是一个元组,就比如,将手机卡,插入了手机
    server.listen(5)  # 半连接池,最大等待连接数为5个,就比如开机
    conn,address = server.accept()  # 接听电话等着别人给你打电话
    ​
    date = conn.recv(1024)  # 听别人说话,接收1023个字节数
    print(date)
    date = conn.recv(1024)  # 听别人说话,接收1023个字节数
    print(date)
    ​
    ​
    conn.close()  # 挂断电话
    server.close()  # 关机

    客户端:

    import socket
    ​
    client = socket.socket()  #拿电话
    client.connect(("127.0.0.1",8088))  #绑定的是IP地址和端口号,也是一个元组 拨号
    ​
    client.send(b"hello")  # 对别人发消息
    client.send(b"hello")  # 对别人发消息
    ​
    ​
    client.close()  # 挂电话

    服务端打印结果:

    b'hellohello'

    这是因为tcp协议会将时间间隔短的,和文件大小小的会一次打包发送给对方

    解决粘包问题:

    struct模块:

    import struct
    ​
    ​
    print("--------------------------1--------------------------")
    msg = "asdasdasdasdasd"
    print("原字符串的长度")
    print(len(msg))
    ​
    handler = struct.pack("i",len(msg))
    print("创建报头的长度")
    print(len(handler))
    ​
    ​
    res = struct.unpack("i",handler)[0]
    print("解报头过后的长度")
    print(res)
    ​
    ​
    ​
    ​
    ​
    print("--------------------------2--------------------------")
    ​
    msg1 = "asdasdasdasdasdasdasdasd"
    print("原字符串的长度")
    print(len(msg1))
    ​
    handler1 = struct.pack("i",len(msg1))
    print("创建报头的长度")
    print(len(handler1))
    ​
    ​
    res1 = struct.unpack("i",handler1)[0]
    print("解报头过后的长度")
    print(res1)
    ​
    """
    --------------------------1--------------------------
    原字符串的长度
    15
    创建报头的长度
    4
    解报头过后的长度
    15
    --------------------------2--------------------------
    原字符串的长度
    24
    创建报头的长度
    4
    解报头过后的长度
    24
    """

    我们可以将报头发过去,然后解报头,就可以知道原来数据的大小,如果这个字节大小比我们接受的大,我们就可以一直让它接收,直到接收完成为止,

    服务端:

    import json
    import os
    import socket
    import struct
    
    server_path = r'/Users/mac/Documents/client-server/server_movie'
    
    server = socket.socket()
    
    ip_port = ('127.0.0.1', 8080)
    
    server.bind(ip_port)
    
    server.listen(5)
    
    conn, addr = server.accept()
    while 1:
    
        head_len = conn.recv(4)
    
        head_len = struct.unpack('i', head_len)[0]
    
        json_head = conn.recv(head_len).decode('utf-8')
    
        head = json.loads(json_head)
    
        file_size = head['file_size']
    
        with open(os.path.join(server_path, head['file_name']), 'wb') as f:
            while file_size:
                if file_size >= 1024:
                    content = conn.recv(1024)
                    f.write(content)
                    file_size -= 1024
                else:
                    content = conn.recv(file_size)
                    f.write(content)
                    break

    客户端:

    import os
    import socket
    import json
    import struct
    
    client = socket.socket()
    
    ip_port = ('127.0.0.1', 8080)
    
    client.connect(ip_port)
    
    head = {
        'file_path': r'/Users/mac/Documents/client-server/client_movie',
        'file_name': None,
        'file_size': None
    }
    movie_list = os.listdir(head['file_path'])
    
    while 1:
        for i, m in enumerate(movie_list, 1):
            print('%s --> %s' % (i, m))
        choice = input('please input movie number:>>').strip()
        if choice.isdigit():
            choice = int(choice)
            if choice in range(1, len(movie_list) + 1):
                movie_name = movie_list[choice - 1]
                head['file_name'] = movie_name
                head['file_size'] = os.path.getsize(os.path.join(head['file_path'], head['file_name']))
                json_head = json.dumps(head).encode('utf-8')
                bytes_head = len(json_head)
                pack_head = struct.pack('i', bytes_head)
                client.send(pack_head)
                client.send(json_head)
                file_size = head['file_size']
                with open(os.path.join(head['file_path'], head['file_name']), 'rb') as f:
                    while file_size:
                        if file_size >= 1024:
                            content = f.read(1024)
                            client.send(content)
                            file_size -= 1024
                        else:
                            content = f.read(file_size)
                            client.send(content)
                            print("finish")
                            break
            else:
                print('index out of range')
        else:
            print('input number...')
  • 相关阅读:
    排序
    最小栈
    移除链表元素
    回文链表
    maven自动建立目录骨架
    maven的结构和构建命令
    递归
    链表的中间结点
    括号匹配
    软件工程个人作业01
  • 原文地址:https://www.cnblogs.com/tulintao/p/11318594.html
Copyright © 2011-2022 走看看