自定义头文件之二------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"); }