posix_quic-master 创建stream

本文详细阐述了在posix_quic项目中创建QUIC流的过程,从QuicCreateStream()开始,深入到CreateOutgoingDynamicStream()函数,讨论了流的优先级设定、流ID的生成机制以及客户端流ID的偶数特性。同时,提到了流的八级优先级与SPDY的关联,以及QuicSession如何管理这些流数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这里主要介绍quic stream的创建

QuicStream stream = QuicCreateStream(fd);//创建stream流

跟进这个QuicCreateStream()函数

QuicStream QuicCreateStream(QuicSocket sock)
{
//先判断传入的套接字
    auto socket = EntryBase::GetFdManager().Get(sock);
    if (!socket || socket->Category() != EntryCategory::Socket) {
        DebugPrint(dbg_api, "sock = %d, return = -1, errno = EBADF", sock);
        errno = EBADF;
        return -1;
    }
//返回一个id
    auto stream = ((QuicSocketEntry*)socket.get())->CreateStream();
    if (!stream) {
        DebugPrint(dbg_api, "sock = %d, return = -1, errno = %d", sock, errno);
        return -1;
    }

    DebugPrint(dbg_api, "sock = %d, newStream = %d", sock, stream->Fd());
    return stream->Fd();
}

//跟进这个CreateStream()

QuicStreamEntryPtr QuicSocketEntry::CreateStream()
{
    if (!IsConnected()) {
        errno = ENOTCONN;	/* Transport endpoint is not connected */
        return QuicStreamEntryPtr();
    }

//首先是if循环语句 判断是否连接 我们跟进这个函数是什么

bool QuicSocketEntry::IsConnected()
{
    return socketState_ == QuicSocketState_Connected;//连接状态
}

创建流的时候返回的是一个QuicStreamEntryPtr()

posix_quic::QuicStreamEntryPtr::shared_ptr() noexcept
constexpr shared_ptr() noexcept
      : __shared_ptr<_Tp>() { }

跟进一下这个函数CreateOutgoingDynamicStream();

QuartcStream* QuartcSession::CreateOutgoingDynamicStream() {
  // Use default priority for incoming QUIC streams.
  // TODO(zhihuang): Determine if this value is correct.
  return ActivateDataStream(CreateDataStream(GetNextOutgoingStreamId(),
                                             QuicStream::kDefaultPriority));
}

在上述函数中我们看到了设置流的优先级 这里采用的是默认的优先级QuicStream::kDefaultPriority,
以及创建流ID的函数 GetNextOutgoingStreamId(),


QuicStreamId QuicSession::GetNextOutgoingStreamId() {
  QuicStreamId id = next_outgoing_stream_id_;
  next_outgoing_stream_id_ += 2;
  return id;
}

我们知道每个流ID都是独一无二的,使用每次增加2的方式改变流ID,使得每个都不相同
客户端创建的流是以偶数形式存在的.

std::unique_ptr<QuartcStream> QuartcSession::CreateDataStream(
    QuicStreamId id,
    SpdyPriority priority) {
  if (crypto_stream_ == nullptr || !crypto_stream_->encryption_established()) {//判断是否加密
    // Encryption not active so no stream created
    return nullptr;
  }
  auto stream = QuicMakeUnique<QuartcStream>(id, this);
  if (stream) {//这个stream不为空
    // Register the stream to the QuicWriteBlockedList. |priority| is clamped
    // between 0 and 7, with 0 being the highest priority and 7 the lowest
    // priority.
    if (!register_streams_early()) {//确保之前没有被登记过
      write_blocked_streams()->RegisterStream(//根据流id和优先级来登记
          stream->id(), /* is_static_stream= */ false, priority);
    } else {//如果之前登记过,那么更新一下优先级别
      write_blocked_streams()->UpdateStreamPriority(stream->id(), priority);
    }

    if (IsIncomingStream(id)) {
      DCHECK(session_delegate_);
      // Incoming streams need to be registered with the session_delegate_.
      session_delegate_->OnIncomingStream(stream.get());
    }
  }
  return stream;
}

An endpoint uses the Stream ID and Offset fields in STREAM frames to place data in order!

// A SPDY priority is a number between 0 and 7 (inclusive).
typedef uint8_t SpdyPriority;

// Lowest and Highest here refer to SPDY priorities as described in
// https://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1#TOC-2.3.3-Stream-priority
const SpdyPriority kV3HighestPriority = 0;
const SpdyPriority kV3LowestPriority = 7;

// Returns SPDY 3.x priority value clamped to the valid range of [0, 7].
SPDY_EXPORT_PRIVATE SpdyPriority ClampSpdy3Priority(SpdyPriority priority);

流是有八个优先级,是根据SPDY的优先级来的
最高级别是0

const SpdyPriority kV3HighestPriority = 0

最低级别是7

const SpdyPriority kV3LowestPriority = 7;

QuicSession拿到这个流的数据 换句话 说就是将stream交付于quicsession管理

return ActivateDataStream(CreateDataStream(GetNextOutgoingStreamId(),
                                             QuicStream::kDefaultPriority));
QuartcStream* QuartcSession::ActivateDataStream(
    std::unique_ptr<QuartcStream> stream) {
  // Transfer ownership of the data stream to the session via ActivateStream().
  QuartcStream* raw = stream.release();
  if (raw) {
    // Make QuicSession take ownership of the stream.
    ActivateStream(std::unique_ptr<QuicStream>(raw));
  }
  return raw;
}
<think>嗯,用户的问题是关于如何选择合适的GCC MinGW-w64版本,特别是x86_64-14.2.0-release的不同子类型。我需要先理解他们的需求,可能他们正在配置开发环境,比如C/C++项目,或者需要交叉编译。首先,我应该考虑操作系统,因为MinGW-w64有不同版本适用于Windows的不同架构。 用户提到了x86_64-14.2.0,这说明他们可能使用的是64位系统。但需要确认他们是否了解不同子类型的区别,比如win32和posix线程模型,以及异常处理机制(seh vs sjlj)。这可能影响他们编译的程序兼容性和性能。 接下来,需求方面,如果他们需要开发跨平台应用,可能需要posix线程,而如果只是Windows应用,win32可能更合适。异常处理方面,64位系统通常用seh,而32位可能用sjlj。此外,运行时库的选择(如ucrt vs msvcrt)也很重要,特别是对于Windows 10及更新版本,ucrt是更好的选择。 然后,我需要整理步骤,指导用户如何根据这些因素选择版本。同时,要提醒他们验证环境变量是否正确配置,比如引用中提到的Path设置问题,可能需要系统变量而不是用户变量,安装后要重启等。此外,引用中的OpenOCD工具安装和Linux程序编译的流程也可能相关,需要确保整个工具链的兼容性。 最后,生成相关问题,帮助用户进一步解决可能遇到的问题,比如验证安装、切换版本、解决兼容性问题等。确保回答结构清晰,分步骤说明,并引用相关资料支持建议。</think>### 如何选择正确的GCC MinGW-w64版本 #### 一、根据操作系统选择架构 1. **Windows系统** - **x86_64**(64位系统):选择`x86_64-*-release`版本,如`x86_64-14.2.0-release` - **i686**(32位系统):选择`i686-*-release`版本 - 注意:64位系统可兼容32位程序,但需显式指定编译参数[^3] 2. **子类型说明** - **win32/posix**:线程模型差异 - `win32`:仅支持Windows API线程 - `posix`:兼容POSIX线程(适用于跨平台开发) - **seh/sjlj**:异常处理机制 - `seh`(结构化异常处理):64位系统首选,性能更高 - `sjlj`(跳转式异常处理):兼容旧系统(如32位程序) #### 二、根据需求选择功能 1. **开发目标** - Windows原生程序:优先选择`win32`线程+`ucrt`运行时 - 跨平台程序:选择`posix`线程(支持C++11多线程特性) 2. **运行时库选择** - **ucrt**(Universal C Runtime):Windows 10+推荐,支持最新API - **msvcrt**:兼容旧版Windows(需注意安全更新限制) #### 三、版本命名示例解析 以`x86_64-14.2.0-release-win32-seh-ucrt`为例: - `x86_64`: 64位架构 - `14.2.0`: GCC版本号 - `win32`: 线程模型 - `seh`: 异常处理机制 - `ucrt`: 运行时库类型 #### 四、验证与配置步骤 1. 下载后需将`mingw64\bin`添加到**系统环境变量**(非用户变量) 2. 打开CMD执行`gcc -v`验证,若提示"no path"需检查环境变量配置[^1] 3. 推荐使用MSYS2管理工具链,支持多版本共存和切换[^2] ```bash # 环境变量验证示例 echo $PATH | grep mingw64 make -v # 验证工具链完整性 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值