zoukankan      html  css  js  c++  java
  • socket套接字

    什么是套接字?

    1. 一组接口
    2. 作用于应用层与传输层之间
    3. 隐藏了传输层下面复杂的TCP/IP协议的实现

    基于TCP协议的socket

    1. 流式协议,面向流的通信是无消息保护边界的
    2. 会将数据少、时间间隔短的数据一次性打包发送
    3. 可靠但粘包
      1. 数据不会丢,包没收完,会继续上次继续接收数据
      2. 数据是可靠的
    4. 只有TCP有粘包现象

    粘包问题:

    产生原因:

    1. 发送的数据小,时间段,TCP会议会自动合成数据,造成粘包。(发送方的缓存机制)
    2. 接收数据只接收一部分,下次接收会继续上次接收数据。(接收方的缓存机制)

    只发生在TCP协议。

    问题的根源:

    ​ 接收方不知道消息的大小

    解决方案:

    1. 发送方提供数据大小
    2. 利用struct模块调用.pack将长度打包header报头发送
    3. 接收方利用struct调用.unpack解包header报头取出长度

    案例:利用subprocess模拟终端命令输入

    客户端										服务端:
    
    1、连接服务									1、开启服务                                                          
    2、发送命令									2、接收客户端命令                                                          
    3、接收header报头						   	3、利用subprocess返回命令结果res
    4、struct.unpack header报头得到字典长度		 4、构造res数据的字典
    5、利用字典长度接收字典					    5、序列化字典,得出序列化后的字典长度
    6、拿出字典里面真实数据长度					  6、利用struct模块构造字典长度的header头
    7、分段接收真实数据							 7、发送header头
    										   8、发送字典
        									   9、发送真实数据
    

    client.py:

    
    
    import socket
    import struct
    import json
    
    
    IP = '127.0.0.1'
    PORT = 8001
    
    client = socket.socket()
    client.connect((IP, PORT))
    
    while True:
        cmd = input('>>>').strip()
        client.send(cmd.encode('utf-8'))
        # 接收字典报头
        data = client.recv(4)
        dict_size = struct.unpack('i', data)[0]
        # 接收字典数据
        dict_data = client.recv(dict_size)
        dic = json.loads(dict_data.decode('utf-8'))
        # 取出数据长度
        file_size = dic.get('file_size')
        #接收真实数据
        recv_size = 0
        real_data = b''
        while recv_size < file_size:
            data = client.recv(1024)
            real_data += data
            recv_size += len(data)
    
        print(real_data.decode('utf-8'))
    

    server.py

    from socket import SOL_SOCKET, SO_REUSEADDR
    import socket
    import subprocess
    import struct
    import json
    
    IP = '127.0.0.1'
    PORT = 8001
    
    server = socket.socket()
    server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    server.bind((IP, PORT))
    server.listen(5)
    
    while True:
        conn, addr = server.accept()
        while True:
            try:
                print('客户端地址:', addr)
                cmd = conn.recv(1024)
                obj = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                res = obj.stdout.read() + obj.stderr.read()
    
                # 构造一个字典
                dic = {'name': 'jason', 'file_size': len(res), 'info': 'great'}
                dump_dict = json.dumps(dic)
    
                # 制作字典报头
                header = struct.pack('i', len(dump_dict))
                # 发送字典报头
                conn.send(header)
                # 发送字典
                conn.send(dump_dict.encode('utf-8'))
                # 发送真实数据
                conn.send(res)
            except ConnectionResetError as e:
                break
    
        conn.close()
    
  • 相关阅读:
    IOS系统下虚拟键盘遮挡文本框问题的解决
    ubuntu git的安装更新及配置
    js 画布与图片的相互转化(canvas与img)
    js 图片与base64互相转换
    PHP base64数据与图片的互相转换
    js 判断当前操作系统是ios还是android还是电脑端
    ubuntu下nodejs和npm的安装及升级
    vue中使用html2canvas及解决html2canvas截屏图片模糊问题
    vue文件中引入外部js
    php 执行 命令行命令
  • 原文地址:https://www.cnblogs.com/KbMan/p/11318630.html
Copyright © 2011-2022 走看看