直播间 网站建设,网站建设+太原,正则表达式匹配网站,网站建设龙岗1. 说明#xff1a;
此篇博客主要记录一种客户端实现方式#xff0c;和两种使用poll或者epoll分别创建echo服务器的方式#xff0c;具体可看代码注释#xff1a;
2. 相关代码#xff1a;
2.1 echoClient.cpp
#include iostream
#include cstdio
#incl…1. 说明
此篇博客主要记录一种客户端实现方式和两种使用poll或者epoll分别创建echo服务器的方式具体可看代码注释
2. 相关代码
2.1 echoClient.cpp
#include iostream
#include cstdio
#include cstring#include arpa/inet.h
#include netinet/in.h
#include sys/socket.h
#include unistd.h#define ERR_EXIT(m) \do {\perror(m); \exit(EXIT_FAILURE); \} while(0)int main() {int sock;struct sockaddr_in svrAddr, localAddr;socklen_t addrlen sizeof(sockaddr);sock socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);if (sock 0)ERR_EXIT(socket);memset(svrAddr, 0, sizeof(svrAddr));svrAddr.sin_family AF_INET;svrAddr.sin_port htons(8888);svrAddr.sin_addr.s_addr inet_addr(127.0.0.1);if (connect(sock, (sockaddr *)svrAddr, sizeof(svrAddr)) 0)ERR_EXIT(connect);if (getsockname(sock, (sockaddr *)localAddr, addrlen) 0)ERR_EXIT(getsockname);std::cout ip inet_ntoa(localAddr.sin_addr) port ntohs(localAddr.sin_port) std::endl;char sendBuf[1024] {0};char recvBuf[1024] {0};while (fgets(sendBuf, sizeof(sendBuf), stdin) ! NULL){write(sock, sendBuf, strlen(sendBuf));read(sock, recvBuf, sizeof(recvBuf));fputs(recvBuf, stdout);memset(sendBuf, 0, sizeof(sendBuf));memset(recvBuf, 0, sizeof(recvBuf));}close(sock);return 0;
}2.2 echoServer_poll.cpp
#include iostream
#include vector
#include string#include cstdio
#include cstring#include arpa/inet.h
#include fcntl.h
#include netinet/in.h
#include unistd.h#include signal.h
#include poll.h
#include sys/socket.h#define ERR_EXIT(m) \do {\perror(m); \exit(EXIT_FAILURE); \} while(0)using PollfdList std::vectorpollfd;int main()
{//忽略系统提示的一些错误信号/*signal(para1,para2)para1:信号类型para2:信号处理函数(可以自定义)讲解参考https://blog.csdn.net/u013271656/article/details/114537411*/signal(SIGPIPE, SIG_IGN);signal(SIGCHLD, SIG_IGN);//创建一个监听套接字(非阻塞套接字)int listenfd;listenfd socket(PF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP);if(listenfd 0){ERR_EXIT(socket);}//设置地址struct sockaddr_in srvAddr;memset(srvAddr,0,sizeof(srvAddr));//初始化srvAddr.sin_family AF_INET;srvAddr.sin_port htons(8888);srvAddr.sin_addr.s_addr htonl(INADDR_ANY);//设置地址的重复利用int on 1;if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, on, sizeof(on)) 0){ERR_EXIT(setsockopt);}//绑定if(bind(listenfd, (sockaddr *)srvAddr, sizeof(srvAddr)) 0){ERR_EXIT(bind);}//监听if(listen(listenfd, SOMAXCONN) 0){ERR_EXIT(listen);}//使用poll并关注pollin事件struct pollfd pfd;pfd.fd listenfd;pfd.events POLLIN;//储存poll的描述符PollfdList pollfds;pollfds.push_back(pfd);int nready;struct sockaddr_in peerAddr;socklen_t peerlen;int connfd;int idlefd;//空闲描述符//循环处理while (true) {//取事件nready poll(pollfds.data(), pollfds.size(), -1);if(nready -1){if(errno EINTR){continue;}ERR_EXIT(poll);}else if(nready 0){continue;}//如果有POLLIN事件if(pollfds[0].revents POLLIN){//接受peerlen sizeof(peerAddr);connfd ::accept4(listenfd, (sockaddr *)peerAddr, peerlen, SOCK_NONBLOCK | SOCK_CLOEXEC);//剔除空闲连接if (connfd -1) {if (errno EMFILE) {close(idlefd);idlefd accept(listenfd, NULL, NULL);close(idlefd);idlefd open(/dev/null, O_RDONLY | O_CLOEXEC);continue;}else ERR_EXIT(accept4);}//加入到监听pfd.fd connfd;pfd.events POLL_IN;pfd.revents 0;pollfds.push_back(pfd);--nready;//连接成功std::cout ip inet_ntoa(peerAddr.sin_addr) port ntohs(peerAddr.sin_port) std::endl;if (nready 0)continue;}//std::cout pollfds size: pollfds.size() std::endl;//std::cout nready fds: nready std::endl;//遍历判断哪些套接字产生了事件for (auto it pollfds.begin() 1; it ! pollfds.end() nready 0; it) {//如果是可读事件if (it-revents POLL_IN) {--nready;connfd it-fd;char buf[1024] {0};//读取数据int ret read(connfd, buf, 1024);if (ret -1)ERR_EXIT(read);if (ret 0) {std::cout client closed std::endl;it pollfds.erase(it);--it;close(connfd);continue;}std::cout buf std::endl;//将接收的消息返回给客户端write(connfd, buf, strlen(buf));}}}return 0;
}2.3 echoServer_epoll.cpp
#include iostream
#include vector
#include string
#include algorithm#include cstdio
#include cstring#include arpa/inet.h
#include fcntl.h
#include netinet/in.h
#include unistd.h#include signal.h
#include sys/epoll.h
#include sys/socket.h#define ERR_EXIT(m) \do {\perror(m); \exit(EXIT_FAILURE); \} while(0)using EventList std::vectorepoll_event;int main()
{signal(SIGPIPE, SIG_IGN);signal(SIGCHLD, SIG_IGN);//创建一个监听套接字(非阻塞套接字)int listenfd;listenfd socket(PF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP);if(listenfd 0){ERR_EXIT(socket);}//设置地址struct sockaddr_in srvAddr;memset(srvAddr,0,sizeof(srvAddr));//初始化srvAddr.sin_family AF_INET;srvAddr.sin_port htons(8888);srvAddr.sin_addr.s_addr htonl(INADDR_ANY);//设置地址的重复利用int on 1;if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, on, sizeof(on)) 0){ERR_EXIT(setsockopt);}//绑定if(bind(listenfd, (sockaddr *)srvAddr, sizeof(srvAddr)) 0){ERR_EXIT(bind);}//监听if(listen(listenfd, SOMAXCONN) 0){ERR_EXIT(listen);}std::vectorint clients;int epollfd epoll_create(EPOLL_CLOEXEC);//使用EPOLLIN并关注EPOLLIN事件struct epoll_event event;event.data.fd listenfd;event.events EPOLLIN;epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, event);//储存epoll的描述符EventList events(16);struct sockaddr_in peerAddr;socklen_t peerlen;int connfd;int idlefd;//空闲描述符int nready;//循环处理while (true) {//取事件nready epoll_wait(epollfd, events.data(), static_castint(events.size()), -1);if(nready -1){if(errno EINTR){continue;}ERR_EXIT(epoll_wait);}else if(nready 0){continue;}if (static_castsize_t(nready) events.size()) {events.resize(events.size() * 2);} for (auto e : events) {if (e.data.fd listenfd) {peerlen sizeof(peerAddr);connfd ::accept4(listenfd, (sockaddr *)peerAddr, peerlen, SOCK_NONBLOCK | SOCK_CLOEXEC);if (connfd -1) {if (errno EMFILE) {close(idlefd);idlefd accept(listenfd, NULL, NULL);close(idlefd);idlefd open(/dev/null, O_RDONLY | O_CLOEXEC);continue;}else ERR_EXIT(accept4);}clients.push_back(connfd);event.data.fd connfd;event.events EPOLLIN;epoll_ctl(epollfd, EPOLL_CTL_ADD, connfd, event);std::cout connection from ip inet_ntoa(peerAddr.sin_addr) port ntohs(peerAddr.sin_port) std::endl;}else if (e.events EPOLLIN) {connfd e.data.fd;char buf[1024] {0};int ret read(connfd, buf, 1024);if (ret -1)ERR_EXIT(read);if (ret 0) {std::cout client closed std::endl;event e; epoll_ctl(epollfd, EPOLL_CTL_DEL, connfd, event);clients.erase(std::remove(clients.begin(), clients.end(), connfd), clients.end());close(connfd);continue;}std::cout msg: buf std::endl;write(connfd, buf, strlen(buf));}}}return 0;
}