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 struct client_accept_parm
{
const TcpReadFunction mReadFunc;
const SocketClosedFunction mClosedFunc;
const TcpReadFunction mReadFunc; /// This function is defined in the test file.
const SocketClosedFunction mClosedFunc; /// This function is defined in the test file.
} ClientAcceptParam;
typedef struct tcp_server_parm
{
const char *mIp; /**Server ip */
const int mPort; /**Server port */
const TcpAcceptClientFunction mAcceptClientFunc;
const ClientAcceptParam mClientAcceptParam;
const char *mIp; /// Server ip
const int mPort; /// Server port
const TcpAcceptClientFunction mAcceptClientFunc; /// This function is defined in the test file.
const ClientAcceptParam mClientAcceptParam; /// This function is defined in the test file.
} TcpServerParam;
typedef struct tcp_parm
{

View File

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

View File

@ -34,7 +34,7 @@ public:
typedef struct i_tcp_client_header
{
const char *mCheckName;
} ITcpClientHeader;
} ITcpClientHeader;
typedef struct tcp_client
{
ITcpClientHeader mHeader;

View File

@ -25,7 +25,7 @@
#include <sys/types.h>
/**
* @brief Called when data is received on a TCP connection.
*
*
* @param io Socket handle
* @param buf The transmitted data content
* @param len Byte length of transmitted data
@ -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)
{
constexpr int NO_FALGS = 0;
mLoop = hloop_new(NO_FALGS); ///Initialize event loop
/// Initialize event loop
mLoop = hloop_new(NO_FALGS);
if (nullptr == mLoop) {
LogError("TcpClientImpl::Init hloop_new failed.\n");
return;
@ -76,9 +78,11 @@ void TcpClientImpl::Init(void)
return;
}
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_connect(io); ///Connection operation
/// Connection operation
hio_connect(io);
mIo = io;
std::shared_ptr<TcpClientImpl> impl = std::dynamic_pointer_cast<TcpClientImpl>(shared_from_this());
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");
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)
{
@ -130,8 +135,8 @@ void TcpClientImpl::Closed(void)
}
}
/**
* @brief Run event loop
*
* @brief Run an event loop and release resources after completion or error.
*
*/
void TcpClientImpl::Loop(void)
{
@ -155,11 +160,12 @@ std::shared_ptr<ITcpClient> *NewTcpClient(const TcpClientParam &param)
memcpy((void *)impl, (void *)&tmp, sizeof(TcpClient));
impl->mHeader.mCheckName = GetTcpClientModuleName();
/**
* @brief ObjectThis points to the first address of the impl and offsets the address by ITcpClientHeader bytes,
* @brief ObjectThis points to the first address of the impl and offsets the address by ITcpClientHeader bytes,
* that is, skips the mHeader part of the impl.
*/
std::shared_ptr<ITcpClient> *objectThis =
(std::shared_ptr<ITcpClient> *)(((char *)impl) + sizeof(ITcpClientHeader));
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);
private:
std::mutex mMutex; ///A mutex lock used to synchronize access to shared resources.
hloop_t *mLoop; ///Event loop, listening for io objects
hio_t *mIo; ///Socket handle
const TcpClientParam mParam; ///Basic information of the client, including port, ip, reading and closing.
std::mutex mMutex; /// A mutex lock used to synchronize access to shared resources.
hloop_t *mLoop; /// Event loop, listening for io objects
hio_t *mIo; /// Socket handle
const TcpClientParam mParam; /// Basic information of the client, including port, ip, reading and closing.
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);
#endif

View File

@ -23,7 +23,7 @@
#include <sys/types.h>
/**
* @brief Verify that object is a legitimate (existing) server.
*
*
* @param object Save the address of the character pointer variable.
* Should be substituted into the private member objectThis of the client instance.
* If the value of the character pointer pointed by *object is "tcp_server", return turn
@ -44,9 +44,9 @@ static bool TcpServerObjectCheck(void *object)
}
/**
* @brief Verify that object is a legitimate (existing) client.
*
*
* @param object Save the address of the character pointer variable.
*
*
* @return true Indicates that the client exists.
* @return false Indicates that the client does not exist
*/

View File

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

View File

@ -24,18 +24,35 @@
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
/**
* @brief Disconnect the connected client.
*
* @param io Socket
*/
static void on_close(hio_t *io)
{
LogInfo("on_close fd=%d error=%d\n", hio_fd(io), hio_error(io));
TcpServerImpl *server = (TcpServerImpl *)hevent_userdata(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)
{
LogInfo("server_on_close fd=%d error=%d\n", hio_fd(io), hio_error(io));
TcpServerImpl *server = (TcpServerImpl *)hevent_userdata(io);
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)
{
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);
(*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)
{
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);
TcpServerImpl *server = (TcpServerImpl *)hevent_userdata(io);
server->AddClient(io);
/// Set up a read event
hio_read_start(io);
}
TcpClientAcceptImpl::TcpClientAcceptImpl(const hio_t *io, const void *object, const ClientAcceptParam &param)
: mIo(io), mObjectThis(object), mParam(param)
{
}
/**
* @brief Disconnect the client
*
*/
void TcpClientAcceptImpl::Close(void)
{
if (nullptr != mIo) {
@ -76,14 +103,28 @@ void TcpClientAcceptImpl::Close(void)
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)
{
if (nullptr != mParam.mReadFunc) {
mParam.mReadFunc(data, length, mObjectThis);
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)
{
if (mIo) {
@ -109,11 +150,15 @@ TcpServerImpl::TcpServerImpl(const TcpServerParam param) : mParam(param)
void TcpServerImpl::Init(void)
{
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) {
LogError("hloop_new failed\n");
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);
if (nullptr == listenio) {
LogError("hloop_create_tcp_server failed\n");
@ -132,11 +177,17 @@ void TcpServerImpl::Init(void)
};
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)
{
LogInfo("UnInit TcpServerImpl\n");
/// Close all client connections
FreeClients();
if (nullptr != mIo) {
/// Turn off connection monitoring
hio_close(mIo);
mIo = nullptr;
}
@ -144,6 +195,10 @@ void TcpServerImpl::UnInit(void)
mTcpServerThread.join();
}
}
/**
* @brief Run an event loop and release resources after completion or error.
*
*/
void TcpServerImpl::Loop(void)
{
if (nullptr == mLoop) {
@ -154,6 +209,11 @@ void TcpServerImpl::Loop(void)
hloop_free(&mLoop);
mLoop = nullptr;
}
/**
* @brief
*
* @param io Add the socket of the newly connected client.
*/
void TcpServerImpl::AddClient(hio_t *io)
{
mMutex.lock();
@ -165,6 +225,9 @@ void TcpServerImpl::AddClient(hio_t *io)
SOCKADDR_STR(hio_peeraddr(io), peeraddrstr));
std::shared_ptr<ITcpClientAccept> *addClient = NewTcpClientAccept(io, mParam.mClientAcceptParam);
mClients[hio_fd(io)] = addClient;
/**
* @brief Check whether the server side accepts the connection of the client side.
*/
if (mParam.mAcceptClientFunc) {
if (mParam.mAcceptClientFunc(addClient, peeraddrstr) == true) {
mMutex.unlock();
@ -176,6 +239,12 @@ void TcpServerImpl::AddClient(hio_t *io)
hio_close(io);
LogWarning("AddClient failed.\n");
}
/**
* @brief
*
* @param io socket
* @return std::shared_ptr<ITcpClientAccept>*
*/
std::shared_ptr<ITcpClientAccept> *TcpServerImpl::GetClient(hio_t *io)
{
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");
return nullptr;
}
/**
* @brief Remove the data element in the map, that is, the connected client.
*
* @param io Socket
*/
void TcpServerImpl::RemoveClient(hio_t *io)
{
std::lock_guard<std::mutex> locker(mMutex);
@ -203,6 +277,10 @@ void TcpServerImpl::RemoveClient(hio_t *io)
LogError("RemoveClient failed, client not exit.\n");
}
}
/**
* @brief Clear all connected clients.
*
*/
void TcpServerImpl::FreeClients(void)
{
std::lock_guard<std::mutex> locker(mMutex);
@ -218,6 +296,10 @@ void TcpServerImpl::FreeClients(void)
}
mClients.clear();
}
/**
* @brief Stop listening to the event loop
*
*/
void TcpServerImpl::Closed(void)
{
if (nullptr != mLoop) {

View File

@ -22,6 +22,11 @@
#include <map>
#include <mutex>
#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>
{
public:
@ -33,10 +38,15 @@ public:
void Closed(void) override;
private:
const hio_t *mIo;
const hio_t *mIo; /// Connected client socket
const void *mObjectThis;
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>
{
public:
@ -44,17 +54,17 @@ public:
virtual ~TcpServerImpl() = default;
void Init(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);
std::shared_ptr<ITcpClientAccept> *GetClient(hio_t *io);
void RemoveClient(hio_t *io);
void FreeClients(void);
void Closed(void);
void RemoveClient(hio_t *io); /// Remove the data element in the map, that is, the connected client.
void FreeClients(void); /// Clear all connected clients.
void Closed(void); /// Stop listening to the event loop(mLoop)
private:
std::mutex mMutex; ///A mutex lock used to synchronize access to shared resources.
hloop_t *mLoop; ///Event loop, listening for io objects
hio_t *mIo; ///Socket handle
std::mutex mMutex; /// A mutex lock used to synchronize access to shared resources.
hloop_t *mLoop; /// Event loop, listening for all io objects
hio_t *mIo; /// listen whether a new client sends a connection request.
const TcpServerParam mParam;
std::thread mTcpServerThread;
std::map<int, std::shared_ptr<ITcpClientAccept> *> mClients;