客户端将数据发送到缓冲区。

void QuicSpdyStream::WriteOrBufferBody(QuicStringPiece data,bool fin,QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {WriteOrBufferData(data, fin, std::move(ack_listener));
}void QuicStream::WriteOrBufferData(QuicStringPiece data,bool fin,QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {if (data.length() > 0) {//将data包装成iovecstruct iovec iov(MakeIovec(data));QuicStreamOffset offset = send_buffer_.stream_offset();if (kMaxStreamLength - offset < data.length()) {QUIC_BUG << "Write too many data via stream " << id_;CloseConnectionWithDetails(QUIC_STREAM_LENGTH_OVERFLOW,QuicStrCat("Write too many data via stream ", id_));return;}//iov put data to send_buffer_send_buffer_.SaveStreamData(&iov, 1, 0, data.length());OnDataBuffered(offset, data.length(), ack_listener);}if (!had_buffered_data && (HasBufferedData() || fin_buffered_)) {// Write data if there is no buffered data before.WriteBufferedData();}}void QuicStreamSendBuffer::SaveStreamData(const struct iovec* iov,int iov_count,size_t iov_offset,QuicByteCount data_length) {size_t slice_len = std::min(data_length, max_data_slice_size);QuicMemSlice slice(allocator_, slice_len);QuicUtils::CopyToBuffer(iov, iov_count, iov_offset, slice_len,const_cast<char*>(slice.data()));                      SaveMemSlice(std::move(slice));                                        }
void QuicStreamSendBuffer::SaveMemSlice(QuicMemSlice slice) {buffered_slices_.emplace_back(std::move(slice), stream_offset_);
}

 缓冲区的数据怎么被取走,并发送到网络中。这次倒着看代码。

bool QuicStreamSendBuffer::WriteStreamData(QuicStreamOffset offset,QuicByteCount data_length,QuicDataWriter* writer) {
// 缓冲区的数据被写进writerif (!writer->WriteBytes(slice_it->slice.data() + slice_offset,copy_length)) {QUIC_BUG << "Writer fails to write.";return false;}
//问题,数据写进writer后,为什么不清除 buffered_slices中对应的数据块?
//此处不清除,什么时候清除?
}
bool QuicStream::WriteStreamData(QuicStreamOffset offset,QuicByteCount data_length,QuicDataWriter* writer) {DCHECK_LT(0u, data_length);QUIC_DVLOG(2) << ENDPOINT << "Write stream " << id_ << " data from offset "<< offset << " length " << data_length;return send_buffer_.WriteStreamData(offset, data_length, writer);
}WriteStreamDataResult QuicSession::WriteStreamData(QuicStreamId id,QuicStreamOffset offset,QuicByteCount data_length,QuicDataWriter* writer) {QuicStream* stream = GetStream(id);if (stream->WriteStreamData(offset, data_length, writer)) {return WRITE_SUCCESS;}
}
//↑ WriteStreamData被AppendStreamFrame调用
bool QuicFramer::AppendStreamFrame(const QuicStreamFrame& frame,bool no_stream_frame_length,QuicDataWriter* writer) {if (data_producer_->WriteStreamData(frame.stream_id, frame.offset,frame.data_length,writer) != WRITE_SUCCESS) {QUIC_BUG << "Writing frame data failed.";return false;}
}
//↑
size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header,const QuicFrames& frames,char* buffer,size_t packet_length){
switch (frame.type){case STREAM_FRAME:if (!AppendStreamFrame(frame.stream_frame, last_frame_in_packet,&writer)) {QUIC_BUG << "AppendStreamFrame failed";return 0;}break;
}
}
//↑
void QuicPacketCreator::SerializePacket(char* encrypted_buffer,size_t encrypted_buffer_len){size_t length = framer_->BuildDataPacket(header, queued_frames_,encrypted_buffer, packet_size_);                                            }//↑
void QuicPacketCreator::Flush(){
SerializePacket(serialized_packet_buffer, kMaxPacketSize);
OnSerializedPacket();//拿到数据,进行回调
}
//↓
void QuicPacketCreator::OnSerializedPacket()
{SerializedPacket packet(std::move(packet_));ClearPacket();delegate_->OnSerializedPacket(&packet);
}
//上文的delegate_为QuicConnection
void QuicConnection::OnSerializedPacket(SerializedPacket* serialized_packet){
SendOrQueuePacket(serialized_packet);
}
void QuicConnection::SendOrQueuePacket(SerializedPacket* packet) {if (!queued_packets_.empty() || !WritePacket(packet)) {}
}
bool QuicConnection::WritePacket(SerializedPacket* packet){WriteResult result = writer_->WritePacket(packet->encrypted_buffer, encrypted_length, self_address().host(),peer_address(), per_packet_options_);
}
quic::WriteResult QuicChromiumPacketWriter::WritePacket(const char* buffer,size_t buf_len,const quic::QuicIpAddress& self_address,const quic::QuicSocketAddress& peer_address,quic::PerPacketOptions* /*options*/) {DCHECK(!IsWriteBlocked());SetPacket(buffer, buf_len);return WritePacketToSocketImpl();
}
//发送到网络中,google封装的socket逻辑。
quic::WriteResult QuicChromiumPacketWriter::WritePacketToSocketImpl() {int rv = socket_->Write(packet_.get(), packet_->size(), write_callback_,kTrafficAnnotation);
}

 解决问题,Flush被那个类调用?

//将缓冲区发送出去的一个总的入口,可以看看这个类都被那些函数调用
void QuicStream::WriteBufferedData() {QuicConsumedData consumed_data =WritevDataInner(write_length, stream_bytes_written(), fin);
}
QuicConsumedData QuicStream::WritevDataInner(size_t write_length,QuicStreamOffset offset,bool fin) {StreamSendingState state = fin ? FIN : NO_FIN;if (fin && add_random_padding_after_fin_) {state = FIN_AND_PADDING;}return session()->WritevData(this, id(), write_length, offset, state);
}
QuicConsumedData QuicSession::WritevData(QuicStream* stream,QuicStreamId id,size_t write_length,QuicStreamOffset offset,StreamSendingState state){QuicConsumedData data =connection_->SendStreamData(id, write_length, offset, state);                                             }
QuicConsumedData QuicConnection::SendStreamData(QuicStreamId id,size_t write_length,QuicStreamOffset offset,StreamSendingState state){
return packet_generator_.ConsumeData(id, write_length, offset, state);                                                    }
QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id,size_t write_length,QuicStreamOffset offset,StreamSendingState state){if (!packet_creator_.ConsumeData(id, write_length, total_bytes_consumed,offset + total_bytes_consumed, fin,has_handshake, &frame)) {// The creator is always flushed if there's not enough room for a new// stream frame before ConsumeData, so ConsumeData should always succeed.QUIC_BUG << "Failed to ConsumeData, stream:" << id;return QuicConsumedData(0, false);}
packet_creator_.Flush();    }bool QuicPacketCreator::ConsumeData(QuicStreamId id,size_t write_length,size_t iov_offset,QuicStreamOffset offset,bool fin,bool needs_full_padding,QuicFrame* frame){CreateStreamFrame(id, write_length, iov_offset, offset, fin, frame);                                      if (!AddFrame(*frame, /*save_retransmittable_frames=*/true)) {// Fails if we try to write unencrypted stream data.return false;}
}

 其中:WriteBufferedData在WriteOrBufferData中被调用过,基本又回到代码分析的起点。
 丢失数据包重传:

bool QuicSentPacketManager::OnAckFrameEnd(QuicTime ack_receive_time){
for (AckedPacket& acked_packet : packets_acked_){MarkPacketHandled(acked_packet.packet_number, info,last_ack_frame_.ack_delay_time);
}PostProcessAfterMarkingPacketHandled(last_ack_frame_, ack_receive_time,rtt_updated_, prior_bytes_in_flight);
}
void QuicSentPacketManager::PostProcessAfterMarkingPacketHandled(const QuicAckFrame& ack_frame,QuicTime ack_receive_time,bool rtt_updated,QuicByteCount prior_bytes_in_flight) {InvokeLossDetection(ack_receive_time);}
void QuicSentPacketManager::InvokeLossDetection(QuicTime time){MarkForRetransmission(packet.packet_number, LOSS_RETRANSMISSION);
}
//MarkForRetransmission is called for different retransmission type
void QuicSentPacketManager::MarkForRetransmission(QuicPacketNumber packet_number,TransmissionType transmission_type){QuicTransmissionInfo* transmission_info =unacked_packets_.GetMutableTransmissionInfo(packet_number);
HandleRetransmission(transmission_type, transmission_info);      }
void QuicSentPacketManager::HandleRetransmission(TransmissionType transmission_type,QuicTransmissionInfo* transmission_info){unacked_packets_.RetransmitFrames(*transmission_info, transmission_type);        }
void QuicUnackedPacketMap::RetransmitFrames(const QuicTransmissionInfo& info,TransmissionType type) {DCHECK(session_decides_what_to_write_);session_notifier_->RetransmitFrames(info.retransmittable_frames, type);
}
void QuicSession::RetransmitFrames(const QuicFrames& frames,TransmissionType type){if (stream != nullptr &&!stream->RetransmitStreamData(frame.stream_frame.offset,frame.stream_frame.data_length,frame.stream_frame.fin)) {break;}                                       }
bool QuicStream::RetransmitStreamData(QuicStreamOffset offset,QuicByteCount data_length,bool fin) {consumed = session()->WritevData(this, id_, retransmission_length,retransmission_offset,can_bundle_fin ? FIN : NO_FIN);
}

 quic协议packet_number与offset信息的记录。

void QuicConnection::SendOrQueuePacket(SerializedPacket* packet){if (!queued_packets_.empty() || !WritePacket(packet)) {// Take ownership of the underlying encrypted packet.//原来的encrypted_buffer指向的是函数栈内的内存packet->encrypted_buffer = CopyBuffer(*packet);queued_packets_.push_back(*packet);packet->retransmittable_frames.clear();}
}
bool QuicConnection::WritePacket(SerializedPacket* packet){bool reset_retransmission_alarm = sent_packet_manager_.OnPacketSent(packet, packet->original_packet_number, packet_send_time,packet->transmission_type, IsRetransmittable(*packet));
}
bool QuicSentPacketManager::OnPacketSent(SerializedPacket* serialized_packet,QuicPacketNumber original_packet_number,QuicTime sent_time,TransmissionType transmission_type,HasRetransmittableData has_retransmittable_data){QuicPacketNumber packet_number = serialized_packet->packet_number; unacked_packets_.AddSentPacket(serialized_packet, original_packet_number,transmission_type, sent_time, in_flight);    }
void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* packet,QuicPacketNumber old_packet_number,TransmissionType transmission_type,QuicTime sent_time,bool set_in_flight){QuicTransmissionInfo info(packet->encryption_level, packet->packet_number_length, transmission_type,sent_time, bytes_sent, has_crypto_handshake, packet->num_padding_bytes);                                             }

quic client的数据发送流程相关推荐

  1. linux网络数据发送流程

    网络套接字如何将数据发生出去的呢?这个需要从网络协议初始化开始分析. 网络协议初始化: 所在文件net/ipv4/af_inet.c static int __init inet_init(void) ...

  2. Linux: 网络数据收发流程简析

    文章目录 1. 前言 2. 背景 3. 网卡数据收发流程 3.1 网络数据接收流程 3.1.1 网卡数据接收流程 3.1.2 网卡数据向上传递给L3,L4的流程 3.2 网卡数据发送流程 1. 前言 ...

  3. STM32 USB数据接收与数据发送程序流程分析

    既然学习了USB,那就必须的搞懂USB设备与USB主机数据是怎么通讯的.这里主要讲设备端,因为我们的代码是做USB设备用的. 我们需要必须要定义了USB中断.起始在STM32的中断向量表中给USB两个 ...

  4. QuteCom手记:phapi发送和接收音频数据的流程(ortp portaudio)

    phapi发送和接收音频数据的流程简介. 通过ortp库(完整的源代码在ortp工程中)实现. oRTP协议将在另外一篇中介绍,这里只要知道它是用来发送和接收媒体流(音频和视频)的协议. 本篇只记录使 ...

  5. 安防视频监控系统视频上云解决方案EasyCVR语音转发功能音频数据打包发送流程介绍

    目前我们的视频上云服务平台EasyCVR已经可集成海康EHome私有协议,并且在前文中我也跟大家讲过EHome协议的配置和调用流程,有兴趣的可以阅读一下:配置及协议介绍.Ehome协议调用流程介绍. ...

  6. LwIP TCP Client 解决长数据发送的困扰

    问题描述 LWIP 的 TCP Client 发送数据可以调用 tcp_write() 函数,将数据储存在缓冲区里面,然后等待超时自动发送或者调用tcp_output()函数进行发送. 然而 tcp_ ...

  7. linux网卡发送数据包流程,linux内核Ethernet以太网卡驱动收发数据过程

    linux内核Ethernet以太网卡驱动收发数据过程 linux内核Ethernet以太网卡驱动收发数据过程 下图简单描述了网卡驱动与Linux内核之间的联系: 关于上图的一些说明: 系统初始化: ...

  8. 2021年大数据Hadoop(十):HDFS的数据读写流程

    2021大数据领域优质创作博客,带你从入门到精通,该博客每天更新,逐渐完善大数据各个知识体系的文章,帮助大家更高效学习. 有对大数据感兴趣的可以关注微信公众号:三帮大数据 目录 HDFS的数据读写流程 ...

  9. hdfs读写流程_深度探索Hadoop分布式文件系统(HDFS)数据读取流程

    一.开篇 Hadoop分布式文件系统(HDFS)是Hadoop大数据生态最底层的数据存储设施.因其具备了海量数据分布式存储能力,针对不同批处理业务的大吞吐数据计算承载力,使其综合复杂度要远远高于其他数 ...

最新文章

  1. 子div超出父div_菜鸟学 react props 子到父
  2. 期末复习、化学反应工程科目(第二章)
  3. Windows Terminal Preview 1.3 发布
  4. 安装运行 rovio odometry
  5. 5.4使用Mockito to mock来测试
  6. 计算机网络模拟校园,计算机网络实验——模拟校园网设计
  7. python批量修改文件后缀名
  8. 【读书笔记】致加西亚的信(二)
  9. DevOps自动化测试的原则和实践
  10. firefox 国际版 账户登录 国内账户 切换 同步问题
  11. 手机+固定电话+传真的正则
  12. python苹果支付(服务端)自动订阅版
  13. socket接口技术和相关函数(socket,bind,listen,accept)
  14. LZO和MiniLZO编码介绍
  15. Pytorch使用VGG做迁移学习(基于 CIFAR100 数据集)
  16. 宠物救助网站-html-前端项目
  17. 好用的分类统计--Python
  18. android7.0root工具,你与玩转Android 7.0,只差一个KingRoot的距离
  19. 助力提升研发效能的“黄金三角”
  20. 3个5相乘列乘法算式_干货 ! 初一数学的21个知识点大总结,再也不怕学不明白...

热门文章

  1. ArduPilot添加新的惯导方案
  2. Mysql - 带条件求和(sum)
  3. 锂电池】关于4.2V锂电池充电IC的一些记录
  4. CDR排钻教程-CorelDRAW服装设计中的排钻技术
  5. xlsx表格怎么筛选重复数据_excel怎么筛选两个表中相同数据
  6. android课程设计健身,健身软件课程设计.doc
  7. UI设计中线性图标设计总结
  8. jadx反编译—下载和使用(傻瓜教程,非常详细)
  9. canvas教程13-使用图片
  10. 【办公-excel】Excel批量翻译