目录一、日志的书写二、套接字Socket的实现一、日志的书写我们直接使用宏来实现日志我们将日志的等级分为三个等级 : INF DBG ERR首先设置什么等级的日志可以打印以便区别测试版本和上线版本使用time函数来获取时间戳 local 将时间戳转化成当前时间struct tm 储存拆分后的结构体strftime按照对应的格式转化成字符串fprintf向标准输出打印 stdout 标准输出%s ts %s FILE %s LINEformat是日志宏的自定义格式参数比如你传的 这是一条日志数字% d\n换行符让每条日志单独一行。##__VA_ARGS__GCC 扩展语法代表「可变参数列表」比如你传的 123, test##是为了处理没有可变参数的情况避免编译错误。二、套接字Socket的实现成员变量文件描述符成员函数创建套接字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;//设置为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; }监听#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; }开启地址重用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); }创建服务端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; }整体代码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); } };