最近在学习quic协议,由于是初学阶段,对这套代码的具体实现还不太熟悉,记录一下对客户端的逻辑分析
在posix_quic-master/test/client/src 文件夹
先是创建socket套接字
//建立套接字
//typedef int posix_quic::QuicSocket
//也就是说QuicSocket就是int数据类型
QuicSocket socket = QuicCreateSocket();
//在quic_socket.cpp文件中 找到QuicCreateSocket()函数
QuicSocket QuicCreateSocket()
{
//auto是自动类型推断关键字
auto socket = QuicSocketEntry::NewQuicSocketEntry(false);
DebugPrint(dbg_api, "socket fd = %d", socket->Fd());
return socket->Fd();
}
第二步是建立connect()连接
//建立udp连接
res = QuicConnect(socket, (struct sockaddr*)&addr, sizeof(addr)
quic是通过流的方式发送数据 所以创建了quic stream
//创建quic stream
QuicStream stream = QuicCreateStream(fd);//创建stream流
//跟踪QuicCreateStream()函数
QuicStream QuicCreateStream(QuicSocket sock)
{//auto 变量自动类型推断
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;
}
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();
}
std::unique_lock<std::recursive_mutex> lock(mtx_);
QuartcStream* stream = impl_->CreateOutgoingDynamicStream();
return QuicStreamEntry::NewQuicStream(shared_from_this(), stream);
}
第三步接收和发送数据
//发送数据
res = QuicWrite(stream, s.c_str(), s.size(), false);
//跟踪一下QuicWrite()函数
ssize_t QuicWrite(QuicStream stream, const void* data, size_t length, bool fin)
{
/*
struct iovec
{
void *iov_base; //Pointer to data.
size_t iov_len; //Length of data.
};
*/
struct iovec iov;
iov.iov_base = (void*)data;
iov.iov_len = length;
return QuicWritev(stream, &iov, 1, fin);
}
接收数据
//接收数据
res = QuicRead(fd, buf, sizeof(buf));//读事件
//跟踪一下QuicRead函数
ssize_t QuicRead(QuicStream stream, void* data, size_t length)
{
struct iovec iov;
iov.iov_base = data;
iov.iov_len = length;
return QuicReadv(stream, &iov, 1);
}
//跟踪一下QuicReadv函数
size_t QuicReadv(QuicStream stream, const struct iovec* iov, int iov_count)
{
auto streamPtr = EntryBase::GetFdManager().Get(stream);
if (!streamPtr || streamPtr->Category() != EntryCategory::Stream) {
DebugPrint(dbg_api, "stream = %d, return = -1, errno = EBADF", stream);
errno = EBADF;
return -1;
}
ssize_t res = ((QuicStreamEntry*)streamPtr.get())->Readv(iov, iov_count);
DebugPrint(dbg_api, "stream = %d, return = %ld, errno = %d", stream, res, errno);
return res;
}
第四步关闭socket连接以及quic stream
//关闭socket连接
QuicCloseSocket(fd);
//跟踪一下这个函数
int QuicCloseSocket(QuicSocket sock)
{
EntryPtr entry = EntryBase::GetFdManager().Get(sock);
if (!entry || entry->Category() != EntryCategory::Socket) {
DebugPrint(dbg_api, "sock = %d, return = -1, errno = EBADF", sock);
errno = EBADF;
return -1;
}
auto socket = std::dynamic_pointer_cast<QuicSocketEntry>(entry);
socket->Close();
QuicSocketEntry::DeleteQuicSocketEntry(socket);
DebugPrint(dbg_api, "sock = %d, return = 0", sock);
return 0;
}
//关闭quic stream
QuicCloseStream(fd);
客户端逻辑上是这样,后期会仔细跟进细节!!!