linux下tcp/udp协议网络通信接口封装+日志打印对象

目录

引入

代码

log.hpp代码


引入

我们可以把之前写过的代码拿过来整合一下,直接封装出网络套接字的接口

  • 这样之后再使用的话,直接调用接口即可
  • 这里写的是tcp协议,也可以修改socket函数里的参数,改为udp协议

代码

cpp 复制代码
#pragma once
 
#include <iostream>
#include <string>
 
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <cstring>
 
#include "Log.hpp"
 
enum
{
    SOCK_ERROR = 2,
    BIND_ERROR,
    LISTEN_ERROR
};
 
int def_log = 10;
 
// 封装出socket接口
class MY_SOCKET
{
public:
    MY_SOCKET()
        : sockfd_(0)
    {
    }
    ~MY_SOCKET()
    {
        Close();
    }
    void Socket()
    {
        sockfd_ = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd_ < 0)
        {
            lg(FATAL, "socket create error, sockfd : %d,%s", sockfd_, strerror(errno));
            exit(SOCK_ERROR);
        }
        lg(INFO, "socket create success, sockfd : %d", sockfd_);
    }
    void Bind(int port)
    {
        struct sockaddr_in *addr = new sockaddr_in;
        memset(addr, 0, sizeof(*addr));
        addr->sin_family = AF_INET;
        addr->sin_addr.s_addr = INADDR_ANY; // 接收任何主机发来的数据包
        addr->sin_port = htons(port);
 
        int t = bind(sockfd_, reinterpret_cast<struct sockaddr *>(addr), sizeof(*addr));
        if (t < 0)
        {
            lg(FATAL, "bind error, sockfd : %d,%s", sockfd_, strerror(errno));
            exit(BIND_ERROR);
        }
        lg(INFO, "bind success, sockfd : %d", sockfd_);
    }
    void Listen()
    {
        if (listen(sockfd_, def_log) < 0)
        {
            lg(FATAL, "listen error, sockfd : %d,%s", sockfd_, strerror(errno));
            exit(LISTEN_ERROR);
        }
        lg(INFO, "listen success, sockfd : %d", sockfd_);
    }
    int Accept(std::string &clientip, uint16_t &clientport)
    {
        sockaddr_in client_addr;
        socklen_t client_len = sizeof(client_addr);
        memset(&client_addr, 0, client_len);
 
        int sockfd = accept(sockfd_, reinterpret_cast<struct sockaddr *>(&client_addr), &client_len);
        if (sockfd < 0)
        {
            lg(WARNING, "accept error, %s: %d", strerror(errno), errno);
            return -1;
        }
        char client_ip[32];
        inet_ntop(AF_INET, &(client_addr.sin_addr), client_ip, sizeof(client_ip));
        clientip = client_ip;
        clientport = ntohs(client_addr.sin_port);
 
        return sockfd;
    }
    bool Connect(const std::string &ip, const uint16_t &port)
    {
        struct sockaddr_in *server_addr = new sockaddr_in;
        memset(server_addr, 0, sizeof(*server_addr));
 
        server_addr->sin_family = AF_INET;
        inet_pton(AF_INET, ip.c_str(), &(server_addr->sin_addr));
        server_addr->sin_port = htons(port);
 
        int ret = connect(sockfd_, reinterpret_cast<struct sockaddr *>(server_addr), sizeof(*server_addr));
        if (ret < 0)
        {
            printf("connect fail : %s:%d\n", ip.c_str(), port);
            return false;
        }
        //printf("connect success\n");
        return true;
    }
    void Close() // tcp协议在初始化好后,就不需要这个套接字了(子进程)
    {
        close(sockfd_);
    }
    int get_fd()
    {
        return sockfd_;
    }
 
public:
    int sockfd_;
};

log.hpp代码

里面用到的lg其实是我们自定义的日志对象

  • 既可以在屏幕上打印,也可以将输出重定向到指定路径的文件里

代码如下:

cpp 复制代码
#pragma once

#include <iostream>
#include <time.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

#define INFO 0
#define DEBUG 1
#define WARNING 2
#define ERROR 3
#define FATAL 4 // 致命的错误

#define SCREEN 1
#define ONEFILE 2

#define DEF_NAME "log.txt"
#define DEF_PATH "./log/"

#define SIZE 1024

class Log
{
public:
    Log()
        : method_(SCREEN), path_(DEF_PATH)
    {
    }
    void enable()
    {
        method_ = ONEFILE;
    }
    void operator()(int level, const char *format, ...)
    {
        time_t t = time(nullptr);
        struct tm *ctime = localtime(&t);

        char leftbuffer[SIZE];
        snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(),
                 ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,
                 ctime->tm_hour, ctime->tm_min, ctime->tm_sec);

        va_list s;
        va_start(s, format);
        char rightbuffer[SIZE];
        vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
        va_end(s);

        // 格式:默认部分+自定义部分
        char logtxt[SIZE * 2];
        snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer, rightbuffer);

        printLog(logtxt);
    }
    ~Log()
    {
    }

private:
    std::string levelToString(int level)
    {
        switch (level)
        {
        case INFO:
            return "INFO";
        case DEBUG:
            return "DEBUG";
        case WARNING:
            return "WARNING";
        case ERROR:
            return "ERROR";
        case FATAL:
            return "FATAL";
        default:
            return "NONE";
        }
    }
    void printLog(const std::string &logtxt)
    {
        switch (method_)
        {
        case SCREEN:
            std::cout << logtxt;
            break;
        case ONEFILE:
            printOneFile(logtxt);
            break;
        default:
            break;
        }
    }
    void printOneFile(const std::string &info)
    {
        std::string path = path_ + DEF_NAME;
        int fd = open(path.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666);
        if (fd > 0)
        {
            write(fd, info.c_str(), info.size());
            close(fd);
        }
        else
        {
            return;
        }
    }

private:
    int method_;
    std::string path_;
};

Log lg;
相关推荐
幻想编织者17 分钟前
Ubuntu实时核编译安装与NVIDIA驱动安装教程(ubuntu 22.04,20.04)
linux·服务器·ubuntu·nvidia
利刃大大1 小时前
【Linux入门】2w字详解yum、vim、gcc/g++、gdb、makefile以及进度条小程序
linux·c语言·vim·makefile·gdb·gcc
飞行的俊哥7 小时前
Linux 内核学习 3b - 和copilot 讨论pci设备的物理地址在内核空间和用户空间映射到虚拟地址的区别
linux·驱动开发·copilot
幽兰的天空8 小时前
介绍 HTTP 请求如何实现跨域
网络·网络协议·http
lisenustc8 小时前
HTTP post请求工具类
网络·网络协议·http
心平气和️8 小时前
HTTP 配置与应用(不同网段)
网络·网络协议·计算机网络·http
心平气和️8 小时前
HTTP 配置与应用(局域网)
网络·计算机网络·http·智能路由器
hunter2062069 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
不会飞的小龙人9 小时前
Docker Compose创建镜像服务
linux·运维·docker·容器·镜像
不会飞的小龙人9 小时前
Docker基础安装与使用
linux·运维·docker·容器