发送流程:
切入点为发送closePacket包:
发送close包会调用
void QuicConnection::CloseConnection(
QuicErrorCode error,
const string& error_details,
ConnectionCloseBehavior connection_close_behavior) //quic_connection.cc 1919行
根据连接状态判断是否已经断开连接,没有则根据状态发送连接断开包
调用SendConnectionClosePacket(error, error_details, NO_ACK/SEND_ACK)ACK代表close包是否捆绑ack
调用完后会 TearDownLocalConnectionState(error, error_details, source);表示关闭当前连接所有状态
函数 QuicConnection::SendConnectionClosePacket
首先调用ClearQueuedPackets(), 其含义是删除在排队的包 (queued_packets_.clear())
之后调用ScopedPacketBundler ack_bundler(this, ack_mode); //绑定ack包
然后创建frame类 QuicConnectionCloseFrame* frame = new QuicConnectionCloseFrame(); //close错误
之后调用
packet_generator_.AddControlFrame(QuicFrame(frame));
为 QuicPacketGenerator::AddControlFrame(const QuicFrame& frame) {
queued_control_frames_.push_back(frame);
SendQueuedFrames(/flush=/false);
}
之后调用 packet_generator_.FlushAllQueuedFrames();
void QuicPacketGenerator::FlushAllQueuedFrames() {
SendQueuedFrames(/flush=/true);
}
因为flush=true
QuicPacketGenerator::SendQueuedFrames 会在进行一系列判断后调用packet_creator_.Flush();
void QuicPacketCreator::Flush() {
if (!HasPendingFrames() && pending_padding_bytes_ == 0) {
return;
}
QUIC_CACHELINE_ALIGNED char serialized_packet_buffer[kMaxPacketSize];
SerializePacket(serialized_packet_buffer, kMaxPacketSize);
OnSerializedPacket();
}
SerializePacket //为加密包
流程:
先创建一个QuicPacketHeader header;
然后调用 FillPacketHeader(&header); packet_number_.单调递增
调用 MaybeAddPadding() 填充包字节
其中会调用 QuicPacketCreator::AddFrame(const QuicFrame& frame,
bool save_retransmittable_frames)
Addframe基本流程为1:判断数据是否加密,没有则错误
2:获取frame_len packet_size_
3:根据frame_type做出相应处理
再调用size_t length = framer_->BuildDataPacket(header, queued_frames_,
encrypted_buffer, packet_size_);
作用是创建一个数据包,具体处理为
size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header,
const QuicFrames& frames,
char* buffer,
size_t packet_length)
先创建QuicDataWriter writer(packet_length, buffer, perspective_, endianness());
再调用AppendPacketHeader(header, &writer) 作用是填写包头包括tag 包类型 包长等
然后根据frame.type进行包的填充
最后返回包长
之后进行包长判断
序列化后ACK帧会被截断,需要返回所有包长
然后判断包长是否正确
最后算出序列化后的包长和
之后会调用函数OnSerializedPacket();
QuicPacketCreator::OnSerializedPacket()
其中会调用OnSerializedPacket(&packet_);
跳转到 QuicConnection::OnSerializedPacket(SerializedPacket* serialized_packet)
调用SendOrQueuePacket(serialized_packet);发送数据包
QuicConnection::SendOrQueuePacket(SerializedPacket* packet)
其中调用WritePacket(packet)
QuicConnection::WritePacket(SerializedPacket* packet)
在该函数中调用了 WriteResult result = writer_->WritePacket()
这个函数根据需求实现,用于向对端发送数据,
QuicSimpleServerPacketWriter::WritePacket(
const char* buffer,
size_t buf_len,
const QuicIpAddress& self_address,
const QuicSocketAddress& peer_address,
PerPacketOptions* options) {
scoped_refptr<StringIOBuffer> buf(
new StringIOBuffer(std::string(buffer, buf_len)));
DCHECK(!IsWriteBlocked());
int rv;
if (buf_len <= static_cast<size_t>(std::numeric_limits<int>::max())) {
rv = socket_->SendTo(
buf.get(), static_cast<int>(buf_len),
peer_address.impl().socket_address(),
base::Bind(&QuicSimpleServerPacketWriter::OnWriteComplete,
weak_factory_.GetWeakPtr()));
} else {
rv = ERR_MSG_TOO_BIG;
}
WriteStatus status = WRITE_STATUS_OK;
if (rv < 0) {
if (rv != ERR_IO_PENDING) {
UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.WriteError", -rv);
status = WRITE_STATUS_ERROR;
} else {
status = WRITE_STATUS_BLOCKED;
write_blocked_ = true;
}
}
return WriteResult(status, rv);
}
这个是quic的例子实现,可以看到用socket进行send,发送了数据
以上是初学者对quic发包过程的一个理解,仅供参考。