此項(xiàng)目是根據(jù)sylar框架實(shí)現(xiàn),是從零開(kāi)始重寫sylar,也是對(duì)sylar豐富與完善
項(xiàng)目地址:https://gitee.com/lzhiqiang1999/server-framework文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-405335.html
簡(jiǎn)介
項(xiàng)目介紹:實(shí)現(xiàn)了一個(gè)基于協(xié)程的服務(wù)器框架,支持多線程、多協(xié)程協(xié)同調(diào)度;支持以異步處理的方式提高服務(wù)器性能;封裝了網(wǎng)絡(luò)相關(guān)的模塊,包括socket、http、servlet等,支持快速搭建HTTP服務(wù)器或WebSokcet服務(wù)器。
詳細(xì)內(nèi)容:日志模塊,使用宏實(shí)現(xiàn)流式輸出,支持同步日志與異步日志、自定義日志格式、日志級(jí)別、多日志分離等功能。線程模塊,封裝pthread相關(guān)方法,封裝常用的鎖包括(信號(hào)量,讀寫鎖,自旋鎖等)。IO協(xié)程調(diào)度模塊,基于ucontext_t實(shí)現(xiàn)非對(duì)稱協(xié)程模型,以線程池的方式實(shí)現(xiàn)多線程,多協(xié)程協(xié)同調(diào)度,同時(shí)依賴epoll實(shí)現(xiàn)了事件監(jiān)聽(tīng)機(jī)制。定時(shí)器模塊,使用最小堆管理定時(shí)器,配合IO協(xié)程調(diào)度模塊可以完成基于協(xié)程的定時(shí)任務(wù)調(diào)度。hook模塊,將同步的系統(tǒng)調(diào)用封裝成異步操作(accept, recv, send等),配合IO協(xié)程調(diào)度能夠極大的提升服務(wù)器性能。Http模塊,封裝了sokcet常用方法,支持http協(xié)議解析,客戶端實(shí)現(xiàn)連接池發(fā)送請(qǐng)求,服務(wù)器端實(shí)現(xiàn)servlet模式處理客戶端請(qǐng)求,支持單Reator多線程,多Reator多線程模式的服務(wù)器。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-405335.html
Socket模塊
1. 主要功能
- 對(duì)Linux下socket相關(guān)方法的封裝,包括bind、listen、connect、read/write系列等方法。
- 支持快速創(chuàng)建TCP、UDP對(duì)應(yīng)的Socket。
2. 功能演示
- 模擬一個(gè)請(qǐng)求百度的客戶端,并打印出響應(yīng)
IPAddress::ptr addr = Address::LookupAnyIPAddress("www.baidu.com:80");
// 創(chuàng)建socket
Socket::ptr socket = Socket::CreateTCP(addr);
// 連接
socket->connect(addr);
//發(fā)送數(shù)據(jù)
const char buf[] = "GET / HTTP/1.1\r\n\r\n";
int rt = socket->send(buf, sizeof(buf));
if(rt <= 0) {
LOG_INFO(g_logger) << "send fail";
return;
}
//接收數(shù)據(jù)
std::string buffers;
buffers.resize(4096);
rt = socket->recv(&buffers[0], 4096);
if(rt <= 0) {
LOG_INFO(g_logger) << "recv fail";
return;
}
LOG_INFO(g_logger) << buffers;
3. 模塊介紹
3.1 Socket
- 對(duì)socket相關(guān)方法的封裝,包括以下內(nèi)容
- 創(chuàng)建各種類型的套接字對(duì)象的方法(TCP套接字,UDP套接字,Unix域套接字)
- 設(shè)置套接字選項(xiàng),比如超時(shí)參數(shù)
- bind/connect/listen方法,實(shí)現(xiàn)綁定地址、發(fā)起連接、發(fā)起監(jiān)聽(tīng)功能
- accept方法,返回連入的套接字對(duì)象
- 發(fā)送、接收數(shù)據(jù)的方法
- 獲取本地地址、遠(yuǎn)端地址的方法
- 獲取套接字類型、地址類型、協(xié)議類型的方法
- 取消套接字讀、寫的方法
class Socket : public std::enable_shared_from_this<Socket>, Noncopyable
{
public:
typedef std::shared_ptr<Socket> ptr;
typedef std::weak_ptr<Socket> weak_ptr;
// 創(chuàng)建TCP Socket(滿足地址類型)
static Socket::ptr CreateTCP(johnsonli::Address::ptr address);
// 創(chuàng)建UDP Socket(滿足地址類型)
static Socket::ptr CreateUDP(johnsonli::Address::ptr address);
// 創(chuàng)建IPv4的TCP Socket
static Socket::ptr CreateTCPSocket();
// 創(chuàng)建IPv4的UDP Socket
static Socket::ptr CreateUDPSocket();
// 創(chuàng)建IPv6的TCP Socket
static Socket::ptr CreateTCPSocket6();
// 創(chuàng)建IPv6的UDP Socket
static Socket::ptr CreateUDPSocket6();
Socket(int family, int type, int protocol = 0);
virtual ~Socket();
int64_t getSendTimeout(); // 獲取發(fā)送超時(shí)時(shí)間(毫秒)
void setSendTimeout(int64_t v); // 設(shè)置發(fā)送超時(shí)時(shí)間(毫秒)
int64_t getRecvTimeout(); // 獲取接受超時(shí)時(shí)間(毫秒)
void setRecvTimeout(int64_t v); // 設(shè)置接受超時(shí)時(shí)間(毫秒)
// 獲取sockopt @see getsockopt
bool getOption(int level, int option, void* result, socklen_t* len);
// 獲取sockopt模板 @see getsockopt
template<class T>
bool getOption(int level, int option, T& result)
{
socklen_t length = sizeof(T);
return getOption(level, option, &result, &length);
}
// 設(shè)置sockopt @see setsockopt
bool setOption(int level, int option, const void* result, socklen_t len);
// 設(shè)置sockopt模板 @see setsockopt
template<class T>
bool setOption(int level, int option, const T& value)
{
return setOption(level, option, &value, sizeof(T));
}
/**
* @brief 接收connect鏈接
* @return 成功返回新連接的socket,失敗返回nullptr
* @pre Socket必須 bind , listen 成功
*/
virtual Socket::ptr accept();
/**
* @brief 綁定地址
* @param[in] addr 地址
* @return 是否綁定成功
*/
virtual bool bind(const Address::ptr addr);
/**
* @brief 連接地址
* @param[in] addr 目標(biāo)地址
* @param[in] timeout_ms 超時(shí)時(shí)間(毫秒)
*/
virtual bool connect(const Address::ptr addr, uint64_t timeout_ms = -1);
virtual bool reconnect(uint64_t timeout_ms = -1);
/**
* @brief 監(jiān)聽(tīng)socket
* @param[in] backlog 未完成連接隊(duì)列的最大長(zhǎng)度
* @result 返回監(jiān)聽(tīng)是否成功
* @pre 必須先 bind 成功
*/
virtual bool listen(int backlog = SOMAXCONN);
/**
* @brief 關(guān)閉socket
*/
virtual bool close();
/**
* @brief 發(fā)送數(shù)據(jù)
* @param[in] buffer 待發(fā)送數(shù)據(jù)的內(nèi)存
* @param[in] length 待發(fā)送數(shù)據(jù)的長(zhǎng)度
* @param[in] flags 標(biāo)志字
* @return
* @retval >0 發(fā)送成功對(duì)應(yīng)大小的數(shù)據(jù)
* @retval =0 socket被關(guān)閉
* @retval <0 socket出錯(cuò)
*/
virtual int send(const void* buffer, size_t length, int flags = 0);
/**
* @brief 發(fā)送數(shù)據(jù)
* @param[in] buffers 待發(fā)送數(shù)據(jù)的內(nèi)存(iovec數(shù)組)
* @param[in] length 待發(fā)送數(shù)據(jù)的長(zhǎng)度(iovec長(zhǎng)度)
* @param[in] flags 標(biāo)志字
* @return
* @retval >0 發(fā)送成功對(duì)應(yīng)大小的數(shù)據(jù)
* @retval =0 socket被關(guān)閉
* @retval <0 socket出錯(cuò)
*/
virtual int send(const iovec* buffers, size_t length, int flags = 0);
/**
* @brief 發(fā)送數(shù)據(jù)
* @param[in] buffer 待發(fā)送數(shù)據(jù)的內(nèi)存
* @param[in] length 待發(fā)送數(shù)據(jù)的長(zhǎng)度
* @param[in] to 發(fā)送的目標(biāo)地址
* @param[in] flags 標(biāo)志字
* @return
* @retval >0 發(fā)送成功對(duì)應(yīng)大小的數(shù)據(jù)
* @retval =0 socket被關(guān)閉
* @retval <0 socket出錯(cuò)
*/
virtual int sendTo(const void* buffer, size_t length, const Address::ptr to, int flags = 0);
/**
* @brief 發(fā)送數(shù)據(jù)
* @param[in] buffers 待發(fā)送數(shù)據(jù)的內(nèi)存(iovec數(shù)組)
* @param[in] length 待發(fā)送數(shù)據(jù)的長(zhǎng)度(iovec長(zhǎng)度)
* @param[in] to 發(fā)送的目標(biāo)地址
* @param[in] flags 標(biāo)志字
* @return
* @retval >0 發(fā)送成功對(duì)應(yīng)大小的數(shù)據(jù)
* @retval =0 socket被關(guān)閉
* @retval <0 socket出錯(cuò)
*/
virtual int sendTo(const iovec* buffers, size_t length, const Address::ptr to, int flags = 0);
/**
* @brief 接受數(shù)據(jù)
* @param[out] buffer 接收數(shù)據(jù)的內(nèi)存
* @param[in] length 接收數(shù)據(jù)的內(nèi)存大小
* @param[in] flags 標(biāo)志字
* @return
* @retval >0 接收到對(duì)應(yīng)大小的數(shù)據(jù)
* @retval =0 socket被關(guān)閉
* @retval <0 socket出錯(cuò)
*/
virtual int recv(void* buffer, size_t length, int flags = 0);
/**
* @brief 接受數(shù)據(jù)
* @param[out] buffers 接收數(shù)據(jù)的內(nèi)存(iovec數(shù)組)
* @param[in] length 接收數(shù)據(jù)的內(nèi)存大小(iovec數(shù)組長(zhǎng)度)
* @param[in] flags 標(biāo)志字
* @return
* @retval >0 接收到對(duì)應(yīng)大小的數(shù)據(jù)
* @retval =0 socket被關(guān)閉
* @retval <0 socket出錯(cuò)
*/
virtual int recv(iovec* buffers, size_t length, int flags = 0);
/**
* @brief 接受數(shù)據(jù)
* @param[out] buffer 接收數(shù)據(jù)的內(nèi)存
* @param[in] length 接收數(shù)據(jù)的內(nèi)存大小
* @param[out] from 發(fā)送端地址
* @param[in] flags 標(biāo)志字
* @return
* @retval >0 接收到對(duì)應(yīng)大小的數(shù)據(jù)
* @retval =0 socket被關(guān)閉
* @retval <0 socket出錯(cuò)
*/
virtual int recvFrom(void* buffer, size_t length, Address::ptr from, int flags = 0);
/**
* @brief 接受數(shù)據(jù)
* @param[out] buffers 接收數(shù)據(jù)的內(nèi)存(iovec數(shù)組)
* @param[in] length 接收數(shù)據(jù)的內(nèi)存大小(iovec數(shù)組長(zhǎng)度)
* @param[out] from 發(fā)送端地址
* @param[in] flags 標(biāo)志字
* @return
* @retval >0 接收到對(duì)應(yīng)大小的數(shù)據(jù)
* @retval =0 socket被關(guān)閉
* @retval <0 socket出錯(cuò)
*/
virtual int recvFrom(iovec* buffers, size_t length, Address::ptr from, int flags = 0);
// 輸出信息到流中
virtual std::ostream& dump(std::ostream& os) const;
virtual std::string toString() const;
bool cancelRead(); // 取消讀
bool cancelWrite(); // 取消寫
bool cancelAccept(); // 取消accept
bool cancelAll(); // 取消所有事件
protected:
void initSock(); // 設(shè)置socket屬性
void newSock(); // 創(chuàng)建socket m_sockfd = socket()
virtual bool init(int sock); // 初始化sock,調(diào)用initSock
protected:
int m_sockfd; /// socket句柄
int m_family; /// 協(xié)議簇
int m_type; /// 類型
int m_protocol; /// 協(xié)議
bool m_isConnected; /// 是否連接
Address::ptr m_localAddress; /// 本地地址
Address::ptr m_remoteAddress; /// 遠(yuǎn)端地址
};
// 流式輸出socket
std::ostream& operator<<(std::ostream& os, const Socket& sock);
}
到了這里,關(guān)于從零開(kāi)始實(shí)現(xiàn)一個(gè)C++高性能服務(wù)器框架----Socket模塊的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!