目录
一、日志的书写
我们直接使用宏来实现日志
我们将日志的等级分为三个等级 : INF DBG ERR

首先设置什么等级的日志可以打印,以便区别测试版本和上线版本

使用time函数来获取时间戳 ,local 将时间戳转化成当前时间,struct tm 储存拆分后的结构体,strftime按照对应的格式转化成字符串,fprintf向标准输出打印 stdout 标准输出,%s = ts %s = FILE %s = LINE format:是日志宏的自定义格式参数(比如你传的 "这是一条日志,数字:% d");"\n":换行符,让每条日志单独一行。##__VA_ARGS__:GCC 扩展语法,代表「可变参数列表」(比如你传的 123, "test"),## 是为了处理没有可变参数的情况(避免编译错误)。

二、套接字Socket的实现
成员变量:
文件描述符
成员函数:
创建套接字

cpp
bool Creat()
{
_sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (_sockfd < 0)
{
ERR_LOG("CREAT SOCKET FAILED");
return false;
}
return true;
}
绑定套接字

cpp
bool Bind(const std::string &ip, uint16_t port)
{
struct sockaddr_in addr;
addr.sin_family = AF_INET;//设置为ipv4
addr.sin_port = htons(port);//转化为大端口
addr.sin_addr.s_addr = inet_addr(ip.c_str());//将点分十进制转化为32字节的整数
socklen_t len = sizeof(struct sockaddr_in);
int ret = bind(_sockfd, (struct sockaddr *)&addr, len);
if (ret < 0)
{
ERR_LOG("BIND FAILED");
return false;
}
return true;
}
监听

cpp
#define MAX_LISTEN 10
bool Listen(int backlog = MAX_LISTEN)
{
int ret = listen(_sockfd, backlog);
if (ret < 0)
{
ERR_LOG("LISTEN FAILED");
return false;
}
return true;
}
链接

cpp
bool Connect(const std::string &ip, uint16_t port)
{
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip.c_str());
socklen_t len = sizeof(struct sockaddr_in);
int ret = connect(_sockfd, (struct sockaddr *)&addr, len);
if (ret < 0)
{
ERR_LOG("Connect FAILED");
return false;
}
return true;
}
接收链接

cpp
int Accpet()
{
int newfd = accept(_sockfd, NULL, NULL);
if (newfd < 0)
{
ERR_LOG("ACCEPT FAILE");
return -1;
}
return newfd;
}
读取数据

cpp
ssize_t Recv(void *buf, size_t len, int flag = 0)
{
ssize_t ret = recv(_sockfd, buf, len, flag);
if (ret < 0)
{
if (errno == EAGAIN || errno == EINTR)
{
return 0;
}
ERR_LOG("RECV FAILED");
return -1;
}
return ret;
}
读取设置为非阻塞

cpp
ssize_t NonBlockRecv(void *buf, size_t len) //
{
return Recv(buf, len, MSG_DONTWAIT); // MSG_DONTWAIT为非阻塞
}
发送数据

cpp
ssize_t Send(const void *buf, size_t len, int flag = 0)
{
ssize_t ret = send(_sockfd, buf, len, flag);
if (ret < 0)
{
if (errno == EAGAIN || errno == EINTR)
{
return 0;
}
ERR_LOG("SEND FAILED");
return -1;
}
return ret;
}
发送设置为非阻塞

cpp
ssize_t NonBlockSend(void *buf, size_t len)
{
if (len == 0)
return 0;
return Send(buf, len, MSG_DONTWAIT);
}
关闭链接

cpp
void Close()
{
if (_sockfd != -1)
{
close(_sockfd);
}
_sockfd = -1;
}
开启地址重用

cpp
void ReuseAddress()
{
int val = 1;
// 端口
setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&val, sizeof(int));
val = 1;
// 接口
setsockopt(_sockfd, SOL_SOCKET, SO_REUSEPORT, (void *)&val, sizeof(int));
}
套接字设置为非阻塞

cpp
void NonBlock()
{
int flag = fcntl(_sockfd, F_GETFL, 0); // 不能覆盖
fcntl(_sockfd, F_SETFL, flag | O_NONBLOCK);
}
创建服务端

cpp
bool CreatServer(uint16_t port, const std::string &ip = "0.0.0.0")
{
if (Creat() == false)
return false;
ReuseAddress();
NonBlock();
if (Bind(ip, port) == false)
return false;
if (Listen() == false)
return false;
return true;
}
创建客户端
cpp
bool CreatClient(uint16_t port, const std::string &ip = "0.0.0.0")
{
if (Creat() == false)
return false;
if (Connect(ip, port) == false)
return false;
return true;
}
整体代码
cpp
class Socket
{
private:
int _sockfd;
public:
Socket() : _sockfd(-1)
{
}
Socket(int sockfd) : _sockfd(sockfd)
{
}
int Fd()
{
return _sockfd;
}
~Socket()
{
Close();
}
bool Creat()
{
_sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (_sockfd < 0)
{
ERR_LOG("CREAT SOCKET FAILED");
return false;
}
return true;
}
bool Bind(const std::string &ip, uint16_t port)
{
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip.c_str());
socklen_t len = sizeof(struct sockaddr_in);
int ret = bind(_sockfd, (struct sockaddr *)&addr, len);
if (ret < 0)
{
ERR_LOG("BIND FAILED");
return false;
}
return true;
}
#define MAX_LISTEN 10
bool Listen(int backlog = MAX_LISTEN)
{
int ret = listen(_sockfd, backlog);
if (ret < 0)
{
ERR_LOG("LISTEN FAILED");
return false;
}
return true;
}
bool Connect(const std::string &ip, uint16_t port)
{
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip.c_str());
socklen_t len = sizeof(struct sockaddr_in);
int ret = connect(_sockfd, (struct sockaddr *)&addr, len);
if (ret < 0)
{
ERR_LOG("Connect FAILED");
return false;
}
return true;
}
int Accpet()
{
int newfd = accept(_sockfd, NULL, NULL);
if (newfd < 0)
{
ERR_LOG("ACCEPT FAILE");
return -1;
}
return newfd;
}
ssize_t Recv(void *buf, size_t len, int flag = 0)
{
ssize_t ret = recv(_sockfd, buf, len, flag);
if (ret < 0)
{
if (errno == EAGAIN || errno == EINTR)
{
return 0;
}
ERR_LOG("RECV FAILED");
return -1;
}
return ret;
}
ssize_t NonBlockRecv(void *buf, size_t len) //
{
return Recv(buf, len, MSG_DONTWAIT); // MSG_DONTWAIT为非阻塞
}
ssize_t Send(const void *buf, size_t len, int flag = 0)
{
ssize_t ret = send(_sockfd, buf, len, flag);
if (ret < 0)
{
if (errno == EAGAIN || errno == EINTR)
{
return 0;
}
ERR_LOG("SEND FAILED");
return -1;
}
return ret;
}
ssize_t NonBlockSend(void *buf, size_t len)
{
if (len == 0)
return 0;
return Send(buf, len, MSG_DONTWAIT);
}
void Close()
{
if (_sockfd != -1)
{
close(_sockfd);
}
_sockfd = -1;
}
bool CreatServer(uint16_t port, const std::string &ip = "0.0.0.0")
{
if (Creat() == false)
return false;
ReuseAddress();
NonBlock();
if (Bind(ip, port) == false)
return false;
if (Listen() == false)
return false;
return true;
}
bool CreatClient(uint16_t port, const std::string &ip = "0.0.0.0")
{
if (Creat() == false)
return false;
if (Connect(ip, port) == false)
return false;
return true;
}
// 设置套接字选项,开启地址端口重用
void ReuseAddress()
{
int val = 1;
// 端口
setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&val, sizeof(int));
val = 1;
// 接口
setsockopt(_sockfd, SOL_SOCKET, SO_REUSEPORT, (void *)&val, sizeof(int));
}
void NonBlock()
{
int flag = fcntl(_sockfd, F_GETFL, 0); // 不能覆盖
fcntl(_sockfd, F_SETFL, flag | O_NONBLOCK);
}
};