add some annotate

This commit is contained in:
chenhaijian 2024-08-02 22:37:34 +08:00
parent c1f5931454
commit 625e9aabb3
9 changed files with 135 additions and 35 deletions

View File

@ -25,15 +25,15 @@ typedef bool (*TcpAcceptClientFunction)(void *, const char *);
typedef void (*SocketClosedFunction)(const void *); typedef void (*SocketClosedFunction)(const void *);
typedef struct client_accept_parm typedef struct client_accept_parm
{ {
const TcpReadFunction mReadFunc; const TcpReadFunction mReadFunc; /// This function is defined in the test file.
const SocketClosedFunction mClosedFunc; const SocketClosedFunction mClosedFunc; /// This function is defined in the test file.
} ClientAcceptParam; } ClientAcceptParam;
typedef struct tcp_server_parm typedef struct tcp_server_parm
{ {
const char *mIp; /**Server ip */ const char *mIp; /// Server ip
const int mPort; /**Server port */ const int mPort; /// Server port
const TcpAcceptClientFunction mAcceptClientFunc; const TcpAcceptClientFunction mAcceptClientFunc; /// This function is defined in the test file.
const ClientAcceptParam mClientAcceptParam; const ClientAcceptParam mClientAcceptParam; /// This function is defined in the test file.
} TcpServerParam; } TcpServerParam;
typedef struct tcp_parm typedef struct tcp_parm
{ {

View File

@ -1,5 +1,6 @@
# TCP模块 # TCP模块
这个项目实现了一个用于网络通信的TCP模块提供了服务器和客户端功能。 这个项目实现了一个用于网络通信的TCP模块提供了服务器和客户端功能。
在网络编程中套接字socket是一个用于网络通信的端点。在客户端和服务器模型中客户端会创建一个套接字来与服务器建立连接而服务器则监听来自客户端的连接请求。一旦连接建立客户端和服务器就可以通过各自的套接字进行数据的发送和接收。
# 涉及的知识 # 涉及的知识
* 网络通信 * 网络通信

View File

@ -60,12 +60,14 @@ TcpClientImpl::TcpClientImpl(const TcpClientParam &param, const void *object) :
{ {
} }
/** /**
* @brief Initialize TCP clients, create event loops, I/O objects, and set callback functions for connection and closure. * @brief Initialize TCP clients, create event loops, I/O objects, and set callback functions for connection and
* closure.
*/ */
void TcpClientImpl::Init(void) void TcpClientImpl::Init(void)
{ {
constexpr int NO_FALGS = 0; constexpr int NO_FALGS = 0;
mLoop = hloop_new(NO_FALGS); ///Initialize event loop /// Initialize event loop
mLoop = hloop_new(NO_FALGS);
if (nullptr == mLoop) { if (nullptr == mLoop) {
LogError("TcpClientImpl::Init hloop_new failed.\n"); LogError("TcpClientImpl::Init hloop_new failed.\n");
return; return;
@ -76,9 +78,11 @@ void TcpClientImpl::Init(void)
return; return;
} }
hevent_set_userdata(io, this); hevent_set_userdata(io, this);
hio_setcb_connect(io, on_connect);///Set the callback function of successful connection, and there is no connection operation. /// Set the callback function of successful connection, and there is no connection operation.
hio_setcb_connect(io, on_connect);
hio_setcb_close(io, on_close); hio_setcb_close(io, on_close);
hio_connect(io); ///Connection operation /// Connection operation
hio_connect(io);
mIo = io; mIo = io;
std::shared_ptr<TcpClientImpl> impl = std::dynamic_pointer_cast<TcpClientImpl>(shared_from_this()); std::shared_ptr<TcpClientImpl> impl = std::dynamic_pointer_cast<TcpClientImpl>(shared_from_this());
auto recvThread = [](std::shared_ptr<TcpClientImpl> tcpClient) { auto recvThread = [](std::shared_ptr<TcpClientImpl> tcpClient) {
@ -115,7 +119,8 @@ ssize_t TcpClientImpl::Write(const void *buf, const size_t bufLenght)
LogError("mIo is nullptr.\n"); LogError("mIo is nullptr.\n");
return TCP_MODULE_WRITE_ERROR; return TCP_MODULE_WRITE_ERROR;
} }
return hio_write(mIo, buf, bufLenght); ///Returns the byte length of a packet.If it fails, an error code is returned. /// Returns the byte length of a packet.If it fails, an error code is returned.
return hio_write(mIo, buf, bufLenght);
} }
void TcpClientImpl::Closed(void) void TcpClientImpl::Closed(void)
{ {
@ -130,7 +135,7 @@ void TcpClientImpl::Closed(void)
} }
} }
/** /**
* @brief Run event loop * @brief Run an event loop and release resources after completion or error.
* *
*/ */
void TcpClientImpl::Loop(void) void TcpClientImpl::Loop(void)
@ -161,5 +166,6 @@ std::shared_ptr<ITcpClient> *NewTcpClient(const TcpClientParam &param)
std::shared_ptr<ITcpClient> *objectThis = std::shared_ptr<ITcpClient> *objectThis =
(std::shared_ptr<ITcpClient> *)(((char *)impl) + sizeof(ITcpClientHeader)); (std::shared_ptr<ITcpClient> *)(((char *)impl) + sizeof(ITcpClientHeader));
impl->mTcpClient = std::make_shared<TcpClientImpl>(param, objectThis); impl->mTcpClient = std::make_shared<TcpClientImpl>(param, objectThis);
return objectThis; ///ObjectThis is used to verify whether the client is legal. /// ObjectThis is used to verify whether the client is legal.
return objectThis;
} }

View File

@ -35,12 +35,12 @@ public:
void Loop(void); void Loop(void);
private: private:
std::mutex mMutex; ///A mutex lock used to synchronize access to shared resources. std::mutex mMutex; /// A mutex lock used to synchronize access to shared resources.
hloop_t *mLoop; ///Event loop, listening for io objects hloop_t *mLoop; /// Event loop, listening for io objects
hio_t *mIo; ///Socket handle hio_t *mIo; /// Socket handle
const TcpClientParam mParam; ///Basic information of the client, including port, ip, reading and closing. const TcpClientParam mParam; /// Basic information of the client, including port, ip, reading and closing.
std::thread mTcpClientThread; std::thread mTcpClientThread;
const void *mObjectThis; ///ObjectThis is used to verify whether the client is legal. const void *mObjectThis; /// ObjectThis is used to verify whether the client is legal.
}; };
std::shared_ptr<ITcpClient> *NewTcpClient(const TcpClientParam &param); std::shared_ptr<ITcpClient> *NewTcpClient(const TcpClientParam &param);
#endif #endif

View File

@ -27,6 +27,7 @@ public:
bool GetServer(const int &fd, std::shared_ptr<ITcpServer> &server); bool GetServer(const int &fd, std::shared_ptr<ITcpServer> &server);
private: private:
/// Store multiple servers
std::map<int, std::shared_ptr<ITcpServer>> mFd; std::map<int, std::shared_ptr<ITcpServer>> mFd;
}; };
#endif #endif

View File

@ -24,18 +24,35 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
/**
* @brief Disconnect the connected client.
*
* @param io Socket
*/
static void on_close(hio_t *io) static void on_close(hio_t *io)
{ {
LogInfo("on_close fd=%d error=%d\n", hio_fd(io), hio_error(io)); LogInfo("on_close fd=%d error=%d\n", hio_fd(io), hio_error(io));
TcpServerImpl *server = (TcpServerImpl *)hevent_userdata(io); TcpServerImpl *server = (TcpServerImpl *)hevent_userdata(io);
server->RemoveClient(io); server->RemoveClient(io);
} }
/**
* @brief Close the port on which the server listens for client connections.
*
* @param io The port on which the server listens for client connections.
*/
static void server_on_close(hio_t *io) static void server_on_close(hio_t *io)
{ {
LogInfo("server_on_close fd=%d error=%d\n", hio_fd(io), hio_error(io)); LogInfo("server_on_close fd=%d error=%d\n", hio_fd(io), hio_error(io));
TcpServerImpl *server = (TcpServerImpl *)hevent_userdata(io); TcpServerImpl *server = (TcpServerImpl *)hevent_userdata(io);
server->Closed(); server->Closed();
} }
/**
* @brief The server processes data
*
* @param io Socket
* @param buf data
* @param readbytes bytes
*/
static void on_recv(hio_t *io, void *buf, int readbytes) static void on_recv(hio_t *io, void *buf, int readbytes)
{ {
LogInfo("on_recv fd=%d readbytes=%d\n", hio_fd(io), readbytes); LogInfo("on_recv fd=%d readbytes=%d\n", hio_fd(io), readbytes);
@ -48,6 +65,11 @@ static void on_recv(hio_t *io, void *buf, int readbytes)
std::shared_ptr<ITcpClientAccept> *client = server->GetClient(io); std::shared_ptr<ITcpClientAccept> *client = server->GetClient(io);
(*client)->Readed((const char *)buf, readbytes); (*client)->Readed((const char *)buf, readbytes);
} }
/**
* @brief Handles a new accept client connection event
*
* @param io Socket for newly accepted client connection
*/
static void on_accept(hio_t *io) static void on_accept(hio_t *io)
{ {
LogInfo("on_accept connfd=%d\n", hio_fd(io)); LogInfo("on_accept connfd=%d\n", hio_fd(io));
@ -63,12 +85,17 @@ static void on_accept(hio_t *io)
// std::shared_ptr<ITcpClientAccept> *client = NewTcpClientAccept(io); // std::shared_ptr<ITcpClientAccept> *client = NewTcpClientAccept(io);
TcpServerImpl *server = (TcpServerImpl *)hevent_userdata(io); TcpServerImpl *server = (TcpServerImpl *)hevent_userdata(io);
server->AddClient(io); server->AddClient(io);
/// Set up a read event
hio_read_start(io); hio_read_start(io);
} }
TcpClientAcceptImpl::TcpClientAcceptImpl(const hio_t *io, const void *object, const ClientAcceptParam &param) TcpClientAcceptImpl::TcpClientAcceptImpl(const hio_t *io, const void *object, const ClientAcceptParam &param)
: mIo(io), mObjectThis(object), mParam(param) : mIo(io), mObjectThis(object), mParam(param)
{ {
} }
/**
* @brief Disconnect the client
*
*/
void TcpClientAcceptImpl::Close(void) void TcpClientAcceptImpl::Close(void)
{ {
if (nullptr != mIo) { if (nullptr != mIo) {
@ -76,14 +103,28 @@ void TcpClientAcceptImpl::Close(void)
hio_close(io); hio_close(io);
} }
} }
/**
* @brief The server reads the data received by tcp connection.
*
* @param data
* @param length bytes
*/
void TcpClientAcceptImpl::Readed(const void *data, size_t length) void TcpClientAcceptImpl::Readed(const void *data, size_t length)
{ {
if (nullptr != mParam.mReadFunc) { if (nullptr != mParam.mReadFunc) {
mParam.mReadFunc(data, length, mObjectThis); mParam.mReadFunc(data, length, mObjectThis);
return; return;
} }
LogWarning("mParam.mClosedFunc is null\n"); LogWarning("mParam.mReadedFunc is null\n");
} }
/**
* @brief The server writes data to the tcp connection.
*
* @param data Written data
* @param length Byte length of written data
* @return ssize_t
* Returns the number of bytes written if the writing is successful, and returns the error code -1 if it fails.
*/
ssize_t TcpClientAcceptImpl::Write(const void *data, size_t length) ssize_t TcpClientAcceptImpl::Write(const void *data, size_t length)
{ {
if (mIo) { if (mIo) {
@ -109,11 +150,15 @@ TcpServerImpl::TcpServerImpl(const TcpServerParam param) : mParam(param)
void TcpServerImpl::Init(void) void TcpServerImpl::Init(void)
{ {
constexpr int NO_FALGS = 0; constexpr int NO_FALGS = 0;
mLoop = hloop_new(NO_FALGS); ///Initialize event loop /// Initialize event loop
/// mLoop is used to manage all I/O objects and the events that occur on them.
mLoop = hloop_new(NO_FALGS);
if (nullptr == mLoop) { if (nullptr == mLoop) {
LogError("hloop_new failed\n"); LogError("hloop_new failed\n");
return; return;
} }
/// Create a listening event to listen whether a new client sends a connection request.
/// Listenio is part of mLoop.
hio_t *listenio = hloop_create_tcp_server(mLoop, mParam.mIp, mParam.mPort, on_accept); hio_t *listenio = hloop_create_tcp_server(mLoop, mParam.mIp, mParam.mPort, on_accept);
if (nullptr == listenio) { if (nullptr == listenio) {
LogError("hloop_create_tcp_server failed\n"); LogError("hloop_create_tcp_server failed\n");
@ -132,11 +177,17 @@ void TcpServerImpl::Init(void)
}; };
mTcpServerThread = std::thread(recvThread, impl); mTcpServerThread = std::thread(recvThread, impl);
} }
/**
* @brief De-initialize the TCP server, close the I/O object and wait for the receiving thread to end.
*
*/
void TcpServerImpl::UnInit(void) void TcpServerImpl::UnInit(void)
{ {
LogInfo("UnInit TcpServerImpl\n"); LogInfo("UnInit TcpServerImpl\n");
/// Close all client connections
FreeClients(); FreeClients();
if (nullptr != mIo) { if (nullptr != mIo) {
/// Turn off connection monitoring
hio_close(mIo); hio_close(mIo);
mIo = nullptr; mIo = nullptr;
} }
@ -144,6 +195,10 @@ void TcpServerImpl::UnInit(void)
mTcpServerThread.join(); mTcpServerThread.join();
} }
} }
/**
* @brief Run an event loop and release resources after completion or error.
*
*/
void TcpServerImpl::Loop(void) void TcpServerImpl::Loop(void)
{ {
if (nullptr == mLoop) { if (nullptr == mLoop) {
@ -154,6 +209,11 @@ void TcpServerImpl::Loop(void)
hloop_free(&mLoop); hloop_free(&mLoop);
mLoop = nullptr; mLoop = nullptr;
} }
/**
* @brief
*
* @param io Add the socket of the newly connected client.
*/
void TcpServerImpl::AddClient(hio_t *io) void TcpServerImpl::AddClient(hio_t *io)
{ {
mMutex.lock(); mMutex.lock();
@ -165,6 +225,9 @@ void TcpServerImpl::AddClient(hio_t *io)
SOCKADDR_STR(hio_peeraddr(io), peeraddrstr)); SOCKADDR_STR(hio_peeraddr(io), peeraddrstr));
std::shared_ptr<ITcpClientAccept> *addClient = NewTcpClientAccept(io, mParam.mClientAcceptParam); std::shared_ptr<ITcpClientAccept> *addClient = NewTcpClientAccept(io, mParam.mClientAcceptParam);
mClients[hio_fd(io)] = addClient; mClients[hio_fd(io)] = addClient;
/**
* @brief Check whether the server side accepts the connection of the client side.
*/
if (mParam.mAcceptClientFunc) { if (mParam.mAcceptClientFunc) {
if (mParam.mAcceptClientFunc(addClient, peeraddrstr) == true) { if (mParam.mAcceptClientFunc(addClient, peeraddrstr) == true) {
mMutex.unlock(); mMutex.unlock();
@ -176,6 +239,12 @@ void TcpServerImpl::AddClient(hio_t *io)
hio_close(io); hio_close(io);
LogWarning("AddClient failed.\n"); LogWarning("AddClient failed.\n");
} }
/**
* @brief
*
* @param io socket
* @return std::shared_ptr<ITcpClientAccept>*
*/
std::shared_ptr<ITcpClientAccept> *TcpServerImpl::GetClient(hio_t *io) std::shared_ptr<ITcpClientAccept> *TcpServerImpl::GetClient(hio_t *io)
{ {
std::lock_guard<std::mutex> locker(mMutex); std::lock_guard<std::mutex> locker(mMutex);
@ -186,6 +255,11 @@ std::shared_ptr<ITcpClientAccept> *TcpServerImpl::GetClient(hio_t *io)
LogError("GetClient failed, client not exit.\n"); LogError("GetClient failed, client not exit.\n");
return nullptr; return nullptr;
} }
/**
* @brief Remove the data element in the map, that is, the connected client.
*
* @param io Socket
*/
void TcpServerImpl::RemoveClient(hio_t *io) void TcpServerImpl::RemoveClient(hio_t *io)
{ {
std::lock_guard<std::mutex> locker(mMutex); std::lock_guard<std::mutex> locker(mMutex);
@ -203,6 +277,10 @@ void TcpServerImpl::RemoveClient(hio_t *io)
LogError("RemoveClient failed, client not exit.\n"); LogError("RemoveClient failed, client not exit.\n");
} }
} }
/**
* @brief Clear all connected clients.
*
*/
void TcpServerImpl::FreeClients(void) void TcpServerImpl::FreeClients(void)
{ {
std::lock_guard<std::mutex> locker(mMutex); std::lock_guard<std::mutex> locker(mMutex);
@ -218,6 +296,10 @@ void TcpServerImpl::FreeClients(void)
} }
mClients.clear(); mClients.clear();
} }
/**
* @brief Stop listening to the event loop
*
*/
void TcpServerImpl::Closed(void) void TcpServerImpl::Closed(void)
{ {
if (nullptr != mLoop) { if (nullptr != mLoop) {

View File

@ -22,6 +22,11 @@
#include <map> #include <map>
#include <mutex> #include <mutex>
#include <thread> #include <thread>
/**
* @brief The server manages the connection life cycle and data interaction of each connected client through this kind
* of instance.
*
*/
class TcpClientAcceptImpl : public ITcpClientAccept, public std::enable_shared_from_this<TcpClientAcceptImpl> class TcpClientAcceptImpl : public ITcpClientAccept, public std::enable_shared_from_this<TcpClientAcceptImpl>
{ {
public: public:
@ -33,10 +38,15 @@ public:
void Closed(void) override; void Closed(void) override;
private: private:
const hio_t *mIo; const hio_t *mIo; /// Connected client socket
const void *mObjectThis; const void *mObjectThis;
const ClientAcceptParam mParam; const ClientAcceptParam mParam;
}; };
/**
* @brief The TcpServerImpl class is responsible for listening to connection requests from clients and creating an
* instance of TcpClientAcceptImpl for each accepted connection.
*
*/
class TcpServerImpl : public ITcpServer, public std::enable_shared_from_this<TcpServerImpl> class TcpServerImpl : public ITcpServer, public std::enable_shared_from_this<TcpServerImpl>
{ {
public: public:
@ -44,17 +54,17 @@ public:
virtual ~TcpServerImpl() = default; virtual ~TcpServerImpl() = default;
void Init(void) override; void Init(void) override;
void UnInit(void) override; void UnInit(void) override;
void Loop(void); void Loop(void); /// Run an event loop and release resources after completion or error.
void AddClient(hio_t *io); void AddClient(hio_t *io);
std::shared_ptr<ITcpClientAccept> *GetClient(hio_t *io); std::shared_ptr<ITcpClientAccept> *GetClient(hio_t *io);
void RemoveClient(hio_t *io); void RemoveClient(hio_t *io); /// Remove the data element in the map, that is, the connected client.
void FreeClients(void); void FreeClients(void); /// Clear all connected clients.
void Closed(void); void Closed(void); /// Stop listening to the event loop(mLoop)
private: private:
std::mutex mMutex; ///A mutex lock used to synchronize access to shared resources. std::mutex mMutex; /// A mutex lock used to synchronize access to shared resources.
hloop_t *mLoop; ///Event loop, listening for io objects hloop_t *mLoop; /// Event loop, listening for all io objects
hio_t *mIo; ///Socket handle hio_t *mIo; /// listen whether a new client sends a connection request.
const TcpServerParam mParam; const TcpServerParam mParam;
std::thread mTcpServerThread; std::thread mTcpServerThread;
std::map<int, std::shared_ptr<ITcpClientAccept> *> mClients; std::map<int, std::shared_ptr<ITcpClientAccept> *> mClients;