深入解析B站androidApp接口:从bilibili.api.ticket.v1.Ticket/GetTicket到SendMsg的技术分析

news2025/5/18 12:41:12

前言

最近一段时间,我对B站的App接口进行了深入分析,特别是关注了认证机制和私信功能的实现。通过逆向工程和网络抓包,发现了B站移动端API的底层工作原理,包括设备标识生成机制、认证流程和消息传输协议。本文将分享这些研究成果,希望能对API安全设计和防护提供一些思考。

B站接口的基本架构

B站的移动端API采用了gRPC作为主要通信协议,这与普通的REST API有较大区别。gRPC使用Protocol Buffers(protobuf)进行数据序列化,具有更高的效率和更严格的类型检查。

gRPC请求结构

B站的API请求通常包含以下几个关键部分:

[压缩标志(1字节)][消息长度(4字节)][Protobuf消息体]
  • 压缩标志:通常是0(不压缩)或1(gzip压缩)
  • 消息长度:大端序的4字节整数,表示消息体的长度
  • 消息体:使用protobuf编码的实际数据

例如,一个典型的请求可能是:

00 00 00 00 52 0A 2A 08 88 F3 EC 8A 01 10 01 18 E4 C7 A0 85 01 20 E9 8D FF E7 07 28 01 32 0F 7B 22 63 6F 6E 74 65 6E 74 22 3A 22 32 22 7D 80 01 01 2A 24 65 65 62 35 35 63 38 37 2D 66 32 36 34 2D 34 39 64 33 2D 61 61 39 62 2D 63 37 36 34 39 66 36 31 39 34 33 38

其中:

  • 00 - 不使用压缩
  • 00 00 00 52 - 消息长度为82字节
  • 剩余部分 - protobuf编码的消息体

设备标识机制深度解析

BUVID生成机制

BUVID (Bilibili Unique Video ID) 是B站用来唯一标识设备的关键值,其生成过程如下:

def generate_buvid(device_id, buvid_type):
    """
    生成BUVID (B站设备唯一标识)
    
    参数:
        device_id: 设备ID (根据buvid_type的不同可以是AndroidID、MAC等)
        buvid_type: BUVID类型 (XX代表Android ID, XY代表MAC地址)
    """
    # 预处理device_id
    if buvid_type == BUVIDType.MAC:
        device_id = device_id.replace(":", "")
        
    # 计算device_id的MD5值并转为大写
    id_md5 = hashlib.md5(device_id.encode('utf-8')).hexdigest().upper()
    
    # ..............(敏感信息脱敏处理)
    
    # 最终BUVID: 类型前缀 + ID_E + MD5
    buvid = buvid_type + id_e + id_md5
    return buvid

BUVID的格式为:XX/XY + 3位特征码 + 32位MD5,共37位字符。

设备指纹(fp_local)生成与BUVID的关系

设备指纹(fp_local)与BUVID密切相关,通常用于二次验证设备身份。fp_local的生成依赖于BUVID,同时也考虑了设备型号和无线电版本信息:

def generate_fp(buvid, device_model, device_radio):
    """
    根据BUVID生成设备指纹
    """
    # 1. 构建基础字符串并计算MD5
    base_str = buvid + device_model + device_radio
    md5_hex = hashlib.md5(base_str.encode('utf-8')).hexdigest()
    
    # 2. 添加时间戳
    time_str = datetime.now().strftime("%Y%m%d%H%M%S")
    
    # 3. 添加随机字符串(16位十六进制)
    random_hex = ''.join(random.choice('0123456789abcdef') for _ in range(16))
    
    # 4. 合并所有部分
    fp_base = md5_hex + time_str + random_hex
    
    # 5. 计算校验和,这里是关键部分。所以随机生成并不能通过验证calculate_checksum就不公布了
    checksum = calculate_checksum(fp_base)
    
    # 6. 返回完整指纹
    return fp_base + checksum

关键点:

  1. fp_local的首32位是由BUVID、设备型号和无线电版本共同决定的MD5值
  2. 接下来14位是生成时的时间戳
  3. 再加上16位随机数据
  4. 最后2位是校验和

BUVID与fp_local的关系验证:

def verify_fp(buvid, fp, device_model, device_radio):
    """验证FP是否与BUVID匹配"""
    # 1. 提取FP中的MD5部分(前32个字符)
    fp_md5 = fp[:32]
    
    # 2. 计算预期的MD5
    base_str = buvid + device_model + device_radio
    expected_md5 = hashlib.md5(base_str.encode('utf-8')).hexdigest()
    
    # 3. 验证MD5部分是否匹配
    if fp_md5 != expected_md5:
        return False
    
    # 4. 验证校验和
    fp_base = fp[:-2]
    expected_checksum = calculate_checksum(fp_base)
    actual_checksum = fp[-2:]
    
    # 5. 返回校验和是否匹配
    return expected_checksum == actual_checksum

这种设计确保了:

  • 设备更换后无法保持相同的指纹
  • 服务器可以验证设备指纹的真实性
  • 可以检测设备信息的篡改

Ticket认证机制分析

JWT格式的Ticket结构

Ticket采用JWT(JSON Web Token)格式,由三部分组成:Header、Payload和Signature。

典型的B站Ticket如下:

eyJhbGciOiJIUzI1NiIsImtpZCI6InMwMyIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NDQ2NTYxNjcsImlhdCI6MTc0NDYyNzA2NywiYnV2aWQiOiJYVUY4MjRFRkQ3NjUyNTE5NzhCOEIyNzlEMDYyODNFQkQ1OTZFIn0.flJFBus6TltpIlD_byS2bM0kzXyQe0o-5ndOnrtuTOc

解析后:

  • Header: {"alg":"HS256","kid":"s03","typ":"JWT"}
  • Payload: {"exp":1744656167,"iat":1744627067,"buvid":"XUF824EFD765251978B8B279D06283EBD596E"}
  • Signature: HMAC-SHA256签名

Ticket获取请求的构造

获取Ticket的请求较为复杂,涉及多层嵌套的protobuf消息和签名计算:

def create_ticket_request(self, device_bin):
    """创建Ticket请求数据"""
    # 创建请求数据
    request_data = bytearray()
    
    # 创建x-fingerprint的值
    fingerprint_value = self.create_fingerprint_value()
    
    # 添加字段1: context (x-fingerprint)
    
    
    # 添加字段1: context (x-exbadbasket)
    
    # 将两个context条目添加到请求中

    
    # 添加字段2: key_id = "ec01"
  
    
    # 添加字段3: sign
  
    
    # 压缩数据
    compressed_data = gzip.compress(bytes(request_data))
    
    # 构造gRPC消息
    # ----------- 此处省略
    
    return bytes(grpc_message)

签名计算的安全性

签名计算是认证系统的核心安全机制:

def calculate_app_sign(self, device_bin, fingerprint_value, exbadbasket_value=b''):
    """计算应用签名"""
    # 签名密钥
    key = b'E2lc5tgtl'  # 注:此处为示例密钥,非真实值
    
    # 将base64编码的device_bin解码
    device_bin_data = base64.b64decode(device_bin)
    
    # 创建HMAC对象
    h = hmac.new(key, digestmod=hashlib.sha256)
    
    # 按特定顺序更新数据
	# 此处脱敏处理,省略
    
    # 获取十六进制摘要
    return h.hexdigest()

Protobuf消息的构造与解析

protobuf字段类型

protobuf编码中,每个字段都由标签和值组成:

  • 标签:(field_number << 3) | wire_type
  • 值:根据wire_type决定编码方式

常见的wire_type:

  • 0: Varint (int32, int64, bool等)
  • 1: 64-bit (fixed64, double等)
  • 2: Length-delimited (string, bytes, embedded messages等)
  • 5: 32-bit (fixed32, float等)

手动构造protobuf消息

没有.proto定义文件时,我们需要手动构造protobuf消息,当然你也可以用现成的库去处理:

def append_tag(self, buf, field_number, wire_type):
    """添加字段标签"""
    tag = (field_number << 3) | wire_type
    self.append_varint(buf, tag)

def append_varint(self, buf, value):
    """添加varint类型的值"""
    while value >= 0x80:
        buf.append((value & 0x7f) | 0x80)
        value >>= 7
    buf.append(value & 0x7f)

def append_string(self, buf, value):
    """添加字符串类型字段"""
    encoded = value.encode('utf-8')
    self.append_varint(buf, len(encoded))  # 长度前缀
    buf.extend(encoded)  # 字符串内容

解析protobuf消息

从二进制数据解析protobuf消息也很关键:

def parse_protobuf(data):
    """解析protobuf格式数据"""
    result = {}
    try:
        offset = 0
        while offset < len(data):
            # 获取字段编号和类型
            field_and_type = data[offset]
            field_num = field_and_type >> 3
            wire_type = field_and_type & 0x07
            offset += 1
            
            # 基于wire_type处理不同类型的数据
            if wire_type == 0:  # Varint
                value = 0
                shift = 0
                while True:
                    b = data[offset]
                    offset += 1
                    value |= ((b & 0x7f) << shift)
                    if not (b & 0x80):
                        break
                    shift += 7
                result[str(field_num)] = value
            elif wire_type == 2:  # Length-delimited
                length = 0
                shift = 0
                while True:
                    b = data[offset]
                    offset += 1
                    length |= ((b & 0x7f) << shift)
                    if not (b & 0x80):
                        break
                    shift += 7
                
                # 尝试解析为字符串、JSON或嵌套消息
                try:
                    string_value = data[offset:offset+length].decode('utf-8')
                    if string_value.startswith('{') and string_value.endswith('}'):
                        try:
                            json_value = json.loads(string_value)
                            result[str(field_num)] = string_value
                        except:
                            result[str(field_num)] = string_value
                    else:
                        result[str(field_num)] = string_value
                except:
                    # 嵌套消息或二进制数据
                    nested_result = parse_protobuf(data[offset:offset+length])
                    if nested_result:
                        result[str(field_num)] = nested_result
                    else:
                        result[str(field_num)] = data[offset:offset+length].hex()
                
                offset += length
            # 处理其他wire_type...
    except Exception as e:
        print(f"Protobuf解析错误: {e}")
    
    return result

私信发送功能详解

私信消息的protobuf结构

私信消息的protobuf结构如下:

消息 {
    field1: {  // 内部消息
        field1: 接收者UID (VarInt)
        field2: 消息类型 (VarInt)
        field3: 序列号 (VarInt)
        field4: 设备标识 (VarInt)
        field5: 标志位 (VarInt)
        field6: 消息内容JSON (String)
        field16: 标志位 (VarInt)
    }
    field5: 消息ID (String)
}

构造和发送私信

def create_and_send_message(self, content, receiver_uid, message_id=None):
    """构造并发送B站私信消息"""
    # 生成消息ID
    if message_id is None:
        message_id = str(uuid.uuid4())
    
    # 创建消息数据
    message_data = bytearray()
    
    # 添加内部消息
    inner_msg = bytearray()
    
    # 添加接收者UID

    
    # 添加消息类型

    
    # 添加序列号
    
    # 添加设备标识

    
    # 添加标志位
   
    # 添加消息内容(JSON格式)
   
    # 添加标志位
    self.append_tag(inner_msg, 16, 0)
    self.append_varint(inner_msg, 1)
    
    # 将内部消息添加到外层消息
    self.append_tag(message_data, 1, 2)
    self.append_varint(message_data, len(inner_msg))
    message_data.extend(inner_msg)
    
    # 添加消息ID
    self.append_tag(message_data, 5, 2)
    self.append_string(message_data, message_id)
    
    # 创建gRPC消息
   
    # 准备请求头
    headers = {
        "APP-KEY": "android64",
        "Content-Type": "application/grpc",
        "User-Agent": "...",
        "buvid": self.buvid,
        "x-bili-device-bin": self.device_bin(),
        "x-bili-fawkes-req-bin": self.fawkes_req_bin(),
        "x-bili-locale-bin": "...",
        "x-bili-metadata-bin": self.generate_bili_metadata(),
        "authorization": f"identify_v1 {self.access_key}",
        "x-bili-ticket": self.ticket
        # 其他必要的头信息...
    }
    
    # 发送请求
    url = "https://app.bilibili.com/bilibili.im.interface.v1.ImInterface/SendMsg"
    response = requests.post(url, headers=headers, data=bytes(grpc_message))
    
    return response

解析Base64编码的错误消息

B站的错误响应常常是Base64编码的protobuf消息:

def parse_base64_protobuf(base64_str):
    """解析Base64编码的protobuf数据"""
    try:
        # 补全padding
        padding = len(base64_str) % 4
        if padding:
            base64_str += '=' * (4 - padding)
        
        # 解码Base64
        decoded_data = base64.b64decode(base64_str)
        
        # 解析protobuf
       
        
        return result
    except Exception as e:
        print(f"解析Base64 protobuf数据失败: {e}")
        return None

例如,错误消息CAISBTIxMDI2GlAKJ3R5cGUuZ29vZ2xlYXBpcy5jb20vYmlsaWJpbGkucnBjLlN0YXR1cxIlCKKkARIf5LiN6IO957uZ6Ieq5bex5Y+R6YCB5raI5oGv5ZOmfg解析后可能包含"不允许给自己发送消息"的提示。

技术要点分析

1. 多层认证机制

B站采用了多层认证策略:

  • BUVID:设备唯一标识
  • fp_local:基于BUVID的设备指纹
  • Ticket:JWT格式的临时凭证
  • access_key:长期授权令牌

这种多层机制增加了伪造身份的难度。

2. 签名验证

请求过程中,多处使用了HMAC签名来确保数据完整性和来源可靠性。例如:

  • Ticket请求中对device_bin和fingerprint_value进行签名
  • JWT格式的Ticket本身也包含签名

3. 设备指纹算法

设备指纹(fp_local)的生成算法具有以下特点:

  • 基于设备特征(BUVID、型号、无线电版本)
  • 包含时间戳,允许追踪指纹生成时间
  • 添加校验和,验证数据完整性
  • 部分随机化,防止完全预测

4. protobuf格式的优势利用

B站充分利用了protobuf的优势:

  • 高效的序列化/反序列化
  • 严格的类型检查
  • 二进制格式难以直接分析和修改
  • 版本兼容性好

5. 协议头中各个值的算法

Ascii 类

user-agent 客户端 UA, 必需.
device_model 设备 Model
device_build 设备 Build
app_ver APP 版本号
mobi_app APP 包类型
app_build APP 版本号
app_build_inner APP 版本号(内部)
x-bili-gaia-vtoken 暂时留空.
x-bili-aurora-eid 未登录留空. 必需.
x-bili-mid 用户 UID, 未登录默认为 0. 必需.
x-bili-aurora-zone 留空. 必需.
x-bili-trace-id 如 16e903399574695df75be114ff63ac64:f75be114ff63ac64:0:0. 需要算法处理. 必需.
authorization 鉴权, 登录时设定为 identify_v1 {access_key}, 未登录时无需此项.
buvid 设备唯一标识, 有自己的一套算法.
bili-http-engine cronet
te trailers

Binary 类

x-bili-fawkes-req-bin 设备 Fawkes 信息,加密信息,必须
x-bili-metadata-bin 使用 Metadata 生成. 加密信息,必须
x-bili-device-bin 设备信息, 加密信息,必须
x-bili-network-bin 设备网络信息, 加密信息,必须
x-bili-restriction-bin 限制信息, 加密信息,必须
x-bili-locale-bin 设备区域信息,加密信息,必须
x-bili-exps-bin 加密信息,必须

安全漏洞与防范建议

通过分析,我发现了几个潜在的安全问题及其防范措施:

1. 设备模拟防范

问题:通过分析可以伪造设备信息,包括BUVID和指纹。

防范措施

  • 增加设备特征采集,如硬件序列号、系统指纹等
  • 引入设备行为特征分析,识别异常行为模式
  • 实施设备绑定策略,限制账号可用设备数量
  • 定期更新设备指纹算法,增加逆向难度

2. 签名密钥保护

问题:客户端存储的签名密钥可能被提取。

防范措施

  • 使用白盒加密技术保护客户端密钥
  • 实施密钥分散存储和动态派生
  • 定期轮换密钥
  • 服务端增加额外验证,不完全依赖客户端签名

3. Protobuf结构保护

问题:通过逆向工程可以分析出protobuf结构。

防范措施

  • 混淆字段名和字段编号
  • 定期更新协议结构
  • 添加冗余或诱饵字段
  • 对关键字段进行额外加密

4. JWT安全加固

问题:JWT可能面临重放攻击或篡改。

防范措施

  • 缩短Token有效期
  • 实施Token绑定(将Token与特定会话或设备绑定)
  • 使用更强的签名算法(如ES256而非HS256)
  • 服务端维护已吊销Token列表

5. 请求频率限制

问题:可能出现API滥用。

防范措施

  • 实施基于账号和设备的请求频率限制
  • 为敏感操作增加验证码或其他人机验证
  • 监控异常请求模式并实施自动封禁
  • 对同一设备的多账号操作进行关联分析

实践经验与优化方向

代码优化

在研究过程中,我发现以下编码实践更有效:

# 更清晰的protobuf构造
def create_message(receiver_id, content):
    msg = bytearray()
    
    # 使用辅助函数增加可读性
    add_varint_field(msg, 1, receiver_id)
    add_string_field(msg, 6, json.dumps({"content": content}))
    
    return msg

调试技巧

分析和调试protobuf消息:

def debug_protobuf(hex_data):
    """将十六进制数据解析为人类可读的形式"""
    data = binascii.unhexlify(hex_data.replace(" ", ""))
    result = parse_protobuf(data)
    
    # 美化输出
    return json.dumps(result, indent=2, ensure_ascii=False)

结语

通过对B站App接口的深入分析,我们不仅理解了其身份验证和消息发送机制,也掌握了protobuf消息的构造和解析技术。这些知识不仅适用于B站,也可以应用到其他使用类似技术栈的应用分析中。

对于API开发者,本文揭示了现代移动应用API安全设计的多层次防护策略,以及可能的改进方向。对于研究者,则提供了一个深入理解gRPC和protobuf在实际应用中如何使用的案例。

希望本文对你了解现代移动应用的API实现有所帮助。记住,技术研究应当遵守伦理和法律边界,尊重平台和用户的权益。

在这里插入图片描述


本文内容仅供学习和研究使用,请勿用于任何非法或违反相关服务条款的目的。使用本文中的技术进行未授权访问或攻击行为可能违反《网络安全法》等相关法律法规,责任自负,如有需要联系作者可通过 dGcgQGludm9rZXlvdQ== (base64decode后查看联系方式) 联系我。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2337791.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

UWP发展历程

通用Windows平台(UWP)发展历程 引言 通用Windows平台(Universal Windows Platform, UWP)是微软为实现"一次编写&#xff0c;处处运行"的愿景而打造的现代应用程序平台。作为微软统一Windows生态系统的核心战略组成部分&#xff0c;UWP代表了从传统Win32应用向现代应…

数据库相关概念,关系型数据库的核心要素,MySQL(特点,安装,环境变量配置,启动,停止,客户端连接),数据模型

目录 数据库相关概念 MySQL&#xff08;特点&#xff0c;安装&#xff0c;环境变量配置&#xff0c;启动和停止&#xff0c;客户端连接&#xff09; MySQL数据库的特点 Windows下安装MySQL MySQL 8.0.36&#xff08;安装版&#xff09; MySQL安装 配置Path环境变量 MySQ…

Facebook隐私保护:从技术到伦理的探索

在这个数字化时代&#xff0c;隐私保护已成为公众关注的焦点。Facebook&#xff0c;作为全球最大的社交媒体平台之一&#xff0c;其用户隐私保护问题更是引起了广泛的讨论。本文将从技术层面和伦理层面探讨 Facebook 在隐私保护方面的努力和挑战。 技术层面的隐私保护 在技术…

香港服务器CPU对比:Intel E3与E5系列核心区别与使用场景

香港服务器的 CPU 配置(核心数与主频)直接决定了其并发处理能力和数据运算效率&#xff0c;例如高频多核处理器可显著提升多线程任务响应速度。在实际业务场景中&#xff0c;不同负载需求对 CPU 架构的要求存在显著差异——以 Intel E3 和 E5 系列为例&#xff0c;由于两者在性…

ChatGPT-o3辅助学术大纲效果如何?

目录 1 引言 2 背景综述 2.1 自动驾驶雷达感知 2.2 生成模型演进&#xff1a;从 GAN 到 Diffusion 3 相关工作 3.1 雷达点云增强与超分辨率 3.2 扩散模型在数据增广中的应用 4 方法论 4.1 问题定义与总览 4.2 数据预处理与雷达→体素表示 4.3 潜在体素扩散网络&…

AI大模型API文档的核心内容概述,以通用框架和典型实现为例

以下是AI大模型API文档的核心内容概述&#xff0c;以通用框架和典型实现为例&#xff1a; 一、API基础架构 1. 基础信息 API类型&#xff1a;RESTful API或gRPC&#xff08;如阿里云通义千问支持HTTPS接口&#xff09;请求方式&#xff1a;通常为POST方法基础URL&#xff1a…

使用pnpm第一次运行项目报错 ERR_PNPM_NO_PKG_MANIFEST No package.json found in E:\

开始用unibestpnpm写一个小程序 运行pnpm init报错 如标题所示没有package.json这个文件 博主犯了一个很愚蠢的错误。。 准备方案手动创建一个json文件 此时才发现没到根目录下&#xff0c;创建了一个项目之后就没有切入文件夹里。 切入根目录再下载就成功啦

手持式三维扫描设备赋能智能汽车制造

随着电动化与智能化趋势的加速&#xff0c;传统逆向工程手段已难以满足复杂零部件的建模需求。 ‌3D逆向建模‌技术&#xff0c;为汽车制造企业提供高效、精准的数字化解决方案。 传统汽车零部件的尺寸检测与建模依赖三坐标测量机&#xff08;CMM&#xff09;或人工测绘&#…

Hutool之DateUtil:让Java日期处理变得更加简单

前言 在Java开发中&#xff0c;日期和时间的处理是一个常见问题。为了简化这个过程&#xff0c;许多开发者会使用第三方工具包&#xff0c;如Hutool。Hutool是一个Java工具包&#xff0c;提供了许多实用的功能&#xff0c;其中之一就是日期处理。日期时间工具类是Hutool的核心包…

Ambari 中移除/重装 yarn 集群中的 NodeManager 节点

文章目录 背景分析解决分析:现有 NodeManager 情况移除:240 服务器上的 NodeManager重新安装:240 服务器上的安装 NodeManager疑问为什么直接添加就可以运行?参考背景 项目中有Spark应用,主要在 yarn 集群中部署。 现在发现 yarn 集群中的节点资源过剩,需要将部分节点移…

小程序在 skyline 下如何开启多行省略

参考&#xff1a;https://developers.weixin.qq.com/community/develop/doc/000a648baacca06e83f1034d66c000 前言 小程序在 skyline 下不支持 line-clamp&#xff0c;想要开启多行省略使用 text 组件的 max-lines 结合 overflow 属性。 解决办法&#xff1a;skyline 下不支…

《MySQL:MySQL数据类型分类》

数据类型分类 数值类 tinyint类型 数值越界测试。 在MySQL中&#xff0c;整型可以指定是有符号的和无符号的&#xff0c;默认是有符号的。 可以通过UNSIGNED来说明某个字段是无符号的。 无符号整型数值越界测试。 如果我们向mysql特定的类型中插入不合法的数据&#xff0c;my…

ZYNQ笔记(八):UART 串口中断

版本&#xff1a;Vivado2020.2&#xff08;Vitis&#xff09; 任务&#xff1a;UART串口中断实验&#xff0c;实现串口中断数据回环&#xff08;接收数据并发送出去&#xff09; 目录 一、介绍 二、硬件设计 三、软件设计 四、效果 一、介绍 ZYNQ 的 UART&#xff08;Unive…

生态篇|多总线融合与网关设计

引言 1. 车内多总线概览 2. 主流车载总线技术对比 3. 网关设计原则与架构 4. 协议转换与映射策略 5. 安全与诊断功能集成

基于autoware1.14的实车部署激光雷达循迹,从建图、定位、录制轨迹巡航点、到实车运行。

1.首先安装autoware &#xff0c;大家可以以下一下博客进行安装&#xff0c;如果缺少库什么的直接问ai安装对应的库就行。ubuntu18.04安装Autoware1.14---GPU版 最全环境配置说明_autoware1.14安装教程-CSDN博客 安装成功后运行&#xff1a; source install/setup.bash roslau…

云计算(Cloud Computing)概述——从AWS开始

李升伟 编译 无需正式介绍亚马逊网络服务&#xff08;Amazon Web Services&#xff0c;简称AWS&#xff09;。作为行业领先的云服务提供商&#xff0c;AWS为全球开发者提供了超过170项随时可用的服务。 例如&#xff0c;Adobe能够独立于IT团队开发和更新软件。通过AWS的服务&…

UE学习记录part18

225 animation blueprint templates: generic animation blueprints 在Animation Blueprint中选择template生成动画蓝图模板 在function中选择blurprintthreadsafeupdateanimation&#xff0c;用于做数据的更新 先创建变量&#xff0c;再将变量再blueprintinitializeanimation…

刀片服务器的散热构造方式

刀片服务器的散热构造是其高密度、高性能设计的核心挑战之一。其散热系统需在有限空间内高效处理多个刀片模块产生的集中热量,同时兼顾能耗、噪音和可靠性。以下从模块化架构、核心散热技术、典型方案对比、厂商差异及未来趋势等方面展开分析: 一、模块化散热架构 刀片服务器…

【每日八股】复习计算机网络 Day1:TCP 的头部结构 + TCP 确保可靠传输 + TCP 的三次握手

文章目录 复习计算机网络 Day1TCP 的头部结构TCP 如何保证可靠传输&#xff1f;1. 数据完整性保障2. 顺序与去重控制3. 流量与拥塞控制4. 连接控制5. 其他辅助机制TCP 可靠传输的保障手段总结 TCP 的三次握手&#xff1f;TCP 为什么要三次握手&#xff1f;TCP 三次握手出现报文…

device_fingerprint、device_id、hmac生成

文章目录 1. 写在前面2. 设备信息3. 数美指纹 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python…