自定义头文件之二------hlib.h(慢慢更新)

这个头文件封装了网络编程中常用的一些操作,也会随着使用慢慢更新。

//    hlib.h
#ifndef HLIB_H
#define HLIB_H

#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include "ErrorSolve.h"
#define MAXLINE 4096

/*

    port: 
        
        端口号
    
    rebind:
    
        开启时,若端口port绑定失败,则继续绑定端口port+1,

        一直到绑定成功为止。

    dependency:

        sys/socket.h

        arpa/inet.h

        ErrorSolve.h    

*/

int create_socket(int port, bool rebind);

/*

    fd: 

        文件描述符

    dependency:    

        fcntl.h、ErrorSolve.h

*/

int setnonblocking(int fd);

/*

    fd:

        被监听的文件描述符    

    epollfd:

        epoll文件描述符

    wr:

        true,加入写事件,false,加入读事件

    dependency:

        sys/epoll.h

*/

void addfd(int fd, int epollfd, int wr);

/*

    fd:

        被监听的文件描述符

    epollfd:

        epoll文件描述符

    attr:

        重写事件的的新属性

    dependency:

        sys/epoll.h

*/

void modfd(int fd, int epollfd, int attr);

/*

    fd:

        被监听的文件描述符

    epollfd:

        epoll文件描述符

    dependency:
.ll
        sys/epoll.h

*/

void removefd(int fd, int epollfd);

#endif
//    hlib.cpp
#include "../include/hlib.h"

int create_socket(int port, bool rebind) {
//    创建TCP套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);

    printf("create socket...\n");

//    初始化服务进程地址信息
    sockaddr_in servaddr {sin_family:AF_INET, sin_port:htons(port), sin_addr:{htonl(INADDR_ANY)}};
        socklen_t servlen = sizeof(servaddr);

        printf("init...\n");

//    绑定套接字和地址信息
        if(bind(sockfd, (sockaddr *)&servaddr, servlen) < 0) {
        //    若rebind为真,则绑定失败时,继续绑定port+1,直到成功
            if(rebind == true) {
                        for(;;) {
                                printf("bind failure...\n");
                                servaddr.sin_port = htons(++port);
                                printf("rebind to port %d...\n", port);
                                if(bind(sockfd, (sockaddr *)&servaddr, servlen) >= 0)
                                        break;
                        }
                } else {
                        ErrorSolve::quit("bind error");
                }
        }

        printf("binding...\n");

//    将sockfd转化成监听套接字
        if(listen(sockfd, 100) < 0)
                ErrorSolve::quit("listen error");

        printf("listening...\n");

        return sockfd;
}

int setnonblocking(int fd) {
//    获得fd当前选项值
    int oldopt = fcntl(fd, F_GETFL);
    if(oldopt < 0) {
        ErrorSolve::quit("fcntl error");
    }

//    向fd中添加nonblocking属性    
    int newopt = oldopt | O_NONBLOCK;
    if(fcntl(fd, F_SETFL, newopt) < 0) {
        ErrorSolve::quit("fcntl e
                rror");
    }

    return oldopt;
}

void addfd(int fd, int epollfd, int wr) {
        epoll_event event {events:EPOLLET, data:{fd}};
//    若wr为真则添加写事件,反之,添加读事件
        if(wr) {
                event.events |= EPOLLOUT;
        } else {
                event.events |= EPOLLIN;
        }
//    将事件加入epollfd的事件集合
        if(epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event) < 0)
                ErrorSolve::quit("epoll_ctl error");
//    将fd设置为非阻塞fd
        setnonblocking(fd);
}

void modfd(int fd, int epollfd, int attr) {
    epoll_event event {evetns:attr, data:{fd}};
//    修改epollfd事件集合中fd的事件
    if(epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &event) < )
        ErrorSolve::quit("epoll_ctl error");
}

void removefd(int fd, int epollfd) {
//    删除epollfd事件集合中关于fd的事件
    if(epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, NULL) < 0)
        ErrorSolve::quit("epoll_ctl error");
}
posted @ 2019-04-14 13:11  mtl6906  阅读(390)  评论(0编辑  收藏  举报