• socket套接字 struct模块


    socket(套接字)
      基于socket实现客户端与服务端通信 

    服务端套接字函数

    s.bind()    绑定(主机,端口号)到套接字

    s.listen()  开始TCP监听

    s.accept()  被动接受TCP客户的连接,(阻塞式)等待连接的到来

     

    客户端套接字函数

    s.connect()    主动初始化TCP服务器连接

    s.connect_ex()  connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

     

    公共用途的套接字函数

    s.recv()       接收TCP数据

    s.send()       发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)

     socket初识

      127.0.0.1:本地回环地址,只能本机访问

    -----------------------------服务端------------------------------
    import socket
    
    server = socket.socket()  # 类似于买手机
    server.bind(('127.0.0.1', 8080))  # 类似于插手机卡   bind((IP,PORT))
    server.listen(5)  # 开机   半连接池
    
    conn, addr = server.accept()  # 待机等待接电话
    
    data = conn.recv(1024)  # 接听别人说话 只接收1024个字节 bytes
    print(data)
    conn.send(b'hello!')  # 跟别人说话
    
    conn.close()  # 关闭通信连接
    server.close()  # 关闭服务端
    
    
    -----------------------------客户端------------------------------
    import socket
    
    client = socket.socket()
    client.connect(('127.0.0.1', 8080))  # 找服务器
    
    client.send(b'hello how much?')
    data = client.recv(1024)
    print(data)
    
    client.close()

     TCP协议的特点

      会将数据量比较小的,并且时间间隔比较短的数据,一次性打包发送给接收端

    -----------------------------服务端------------------------------
    import socket
    
    server = socket.socket()
    server.bind(('127.0.0.1',8088))
    server.listen(5)  # 半连接池
    
    
    conn,addr = server.accept()
    data = conn.recv(1024)
    print(data)
    data = conn.recv(1024)
    print(data)
    data = conn.recv(1024)
    print(data)
    
    >>>:b'hellohellohello'
       b''
       b''
    
    
    -----------------------------客户端------------------------------
    import socket
    
    client = socket.socket()
    client.connect(('127.0.0.1',8088))
    
    
    client.send(b'hello')
    client.send(b'hello')
    client.send(b'hello')            

    通信循环

    -----------------------------服务端------------------------------
    import socket
    
    """
    服务端:
    要有固定的ip和port
    24小时不间断提供服务
    """
    server = socket.socket()
    server.bind(('127.0.0.1', 8080))
    server.listen(5)
    
    conn, addr = server.accept()  # 阻塞
    
    while True:
        try:
            data = conn.recv(1024)  # 阻塞
            if len(data) == 0: break  # 针对linux和mac系统 客户端异常断开反复收空的情况
            print(data)
            conn.send(data.upper())
        except ConnectionResetError:
            break
    
    conn.close()
    server.close()
    
    
    -----------------------------客户端------------------------------
    import socket
    
    client = socket.socket()
    client.connect(('127.0.0.1', 8080))
    
    while True:
        msg = input('>>>:').encode('utf-8')
        if len(msg) == 0: continue
        client.send(msg)
        data = client.recv(1024)
        print(data)

    struct模块

    import struct
    
    data = 'seionksngjgm,xmdnabnk ko'
    res = struct.pack('i',len(data))
    
    print('res:',res)   # res: b'x18x00x00x00'
    print('len(res):',len(res))  # 4
    
    
    ret = struct.unpack('i',res)
    print('ret:',ret)  # (24,)
    print('ret[0]:',ret[0])  # 24

    链接循环

    -----------------------------服务端------------------------------
    import socket
    import subprocess
    import struct
    import json
    
    """
    服务端:
    要有固定的ip和port
    24小时不间断提供服务
    """
    server = socket.socket()
    server.bind(('127.0.0.1', 8081))
    server.listen(5)  # 半连接池
    
    while True:
        conn, addr = server.accept()  # 阻塞
        while True:
            try:
                data = conn.recv(1024).decode('utf-8')  # 阻塞
                if len(data) == 0: break  # 针对linux和mac系统 客户端异常断开反复收空的情况
                obj = subprocess.Popen(data, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                stdout = obj.stdout.read()
                stderr = obj.stderr.read()
                print(len(stdout + stderr))
    
                header_dic = {
                    'filename': 'cls.av',
                    'len': len(stdout + stderr)
                }
                header_bytes = json.dumps(header_dic).encode('utf-8')
                # 制作报头
                header = struct.pack('i', len(header_bytes))  # 将需要发送给客户端的数据打包成固定4个字节
                conn.send(header)
    
                conn.send(header_bytes)
    
                conn.send(stdout + stderr)
    
            except ConnectionResetError:
                break
        conn.close()
    
    server.close()
    
    
    
    -----------------------------客户端------------------------------
    import socket
    import struct
    import json
    
    client = socket.socket()
    client.connect(('127.0.0.1', 8081))
    
    while True:
        msg = input('>>>:').encode('utf-8')
        if len(msg) == 0: continue
        client.send(msg)
        header = client.recv(4)
        # 对这个头进行解包,获取真实数据的长度
    
        head_len = struct.unpack('i', header)[0]
        head_dic = json.loads(client.recv(head_len).decode('utf-8'))
        print(head_dic)
        # 对需要接受的数据 进行循环接收
        total_size = head_dic['len']
        recv_size = 0
        res = b''
        while recv_size < total_size:
            data = client.recv(1024)
            res += data
            recv_size += len(data)
        print(res.decode('gbk'))

    粘包问题

    -----------------------------服务端------------------------------
    import socket
    
    """
    服务端:
    要有固定的ip和port
    24小时不间断提供服务
    """
    server = socket.socket()
    server.bind(('127.0.0.1', 8080))
    server.listen(5)  # 半连接池
    
    while True:
        conn, addr = server.accept()  # 阻塞
        while True:
            try:
                data = conn.recv(1024)  # 阻塞
                if len(data) == 0: break  # 针对linux和mac系统 客户端异常断开反复收空的情况
                print(data)
                conn.send(data.upper())
            except ConnectionResetError:
                break
        conn.close()
    
    server.close()
    
    
    
    -----------------------------客户端------------------------------
    import socket
    
    client = socket.socket()
    client.connect(('127.0.0.1', 8080))
    
    while True:
        msg = input('>>>:').encode('utf-8')
        if len(msg) == 0: continue
        client.send(msg)
        data = client.recv(1024)
        print(data)

    为什么会出现粘包现象

    首先:只有在TCP协议中才会出现粘包现象,因为TCP协议是流式协议
    特点:TCP协议会将数据量小并且时间间隔比较短的数据一次性打包发送出去
    本质:其实还是因为我们不知道需要接收的数据的长短

    # 如何解决粘包问题?
    # 1 发送数据直接先告诉对方数据量的大小
    # 2 利用struct模块定制我们自己的消息传输协议 

    最终方法:解决粘包问题
     1.先发报头
     2.再发字典
     3.再发你的真实数据
     
     
     1.先收4个长度的报头
     2.解包拿到字典数据长度
     3.接收字典(反序列化) 》》》  获取字典里面所有信息
     4.接收真实数据

  • 相关阅读:
    Javascript自动垃圾收集机制
    Javascript深入浅出(二)
    Javascript深入浅出(一)
    递归&循环&迭代&遍历&枚举,知多少
    事件流、事件处理程序和事件对象
    弹性布局学习笔记
    css3 伪元素
    css3伪类选择器nth-of-type,:nth-last-of-type,:first-of-type,:last-of-type,:only-of-type
    css3结构伪类选择器first-child,last-child,nth-child(),nth-last-child(),only-child
    css3状态伪类选择器:checked修改按钮默认样式
  • 原文地址:https://www.cnblogs.com/zhouyongv5/p/10797998.html
Copyright © 2020-2023  润新知