初玩linux epoll------一个服务器如何与多个客户端进行通信? (笔试面试常考)
2017-06-24 17:41
731 查看
select和poll被鄙视得厉害, 因为有了linux epoll的存在。 网上讲解select/poll/epoll的例子不胜枚举, 各种比喻, 各种图示。 其实, epoll并没有那么玄乎。 本文中, 我们不进行画图讲解, 也尽量避免过多的文字描述, 只是初步来感受一下epoll.
服务端代码为:
本文只是epoll的一个简单开始, 比较基础, 后面我们还会进行更多的介绍, 便于深入理解其思路。
服务端代码为:
#include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <errno.h> #include <malloc.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/ioctl.h> #include <stdarg.h> #include <fcntl.h> #include <fcntl.h> #include <sys/poll.h> #include <sys/epoll.h> #define BACKLOG 100 int main() { int iListenSock = socket(AF_INET, SOCK_STREAM, 0); sockaddr_in addr; memset(&addr, 0, sizeof(addr)); inet_aton("0.0.0.0", &addr.sin_addr); addr.sin_family = AF_INET; addr.sin_port = htons(8888); int iOpt = 1; setsockopt(iListenSock, SOL_SOCKET, SO_REUSEADDR, &iOpt, sizeof(iOpt)); // 标配 bind(iListenSock, (sockaddr*)&addr, sizeof(addr)); listen(iListenSock, BACKLOG); epoll_event ev; ev.data.fd = iListenSock; ev.events = EPOLLIN; epoll_event events[BACKLOG + 1]; int epollFD = epoll_create(BACKLOG + 1); // 告诉内核监测的数目, 返回的epollFD为epoll管理句柄 epoll_ctl(epollFD, EPOLL_CTL_ADD, iListenSock, &ev); // 将ev和对应的iListenSock添加到epoll句柄,用于被epollFD管理 while(1) { int timeoutMS = -1; // 永不超时 int nfds = epoll_wait(epollFD, events, BACKLOG + 1, timeoutMS); // events和nfds是一对输出值 printf("nfds is %d\n", nfds); for(int i = 0; i < nfds; i++) { if(events[i].data.fd == iListenSock) // 用于监听客户端连接的socket { int iConnSock = accept(iListenSock, NULL, NULL); if (iConnSock < 0) { continue; } ev.data.fd = iConnSock; ev.events = EPOLLIN; epoll_ctl(epollFD, EPOLL_CTL_ADD, iConnSock, &ev); // 将ev和对应的iConnSock添加到epoll句柄,用于被epollFD管理 printf("new sock came, fd is %d\n", iConnSock); } else { int iConnSock = events[i].data.fd; // 用于通信的socket char szBuf[1024] = {0}; int recvLen = recv(iConnSock, szBuf, sizeof(szBuf) - 1, 0); if (recvLen > 0) { printf("recv data [%s] from fd [%d]\n", szBuf, iConnSock); } else if(0 == recvLen) { ev.data.fd = iConnSock; epoll_ctl(epollFD, EPOLL_CTL_DEL, iConnSock, &ev); close(iConnSock); printf("connection closed, local fd is [%d]\n", iConnSock); } else { ev.data.fd = iConnSock; epoll_ctl(epollFD, EPOLL_CTL_DEL, iConnSock, &ev); close(iConnSock); printf("recv error, local fd is [%d]\n", iConnSock); } } } } close(epollFD); close(iListenSock); return 0; }客户端代码为:
#include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <errno.h> #include <malloc.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/ioctl.h> #include <stdarg.h> #include <fcntl.h> #include <fcntl.h> int main() { int sockClient = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in addrSrv; addrSrv.sin_addr.s_addr = inet_addr("127.0.0.1"); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(8888); connect(sockClient, ( const struct sockaddr *)&addrSrv, sizeof(struct sockaddr_in)); char szSendBuf[100] = "this is me"; while(1) { send(sockClient, szSendBuf, strlen(szSendBuf) + 1, 0); scanf("%s", szSendBuf); } close(sockClient); return 0; }makefile代码为:
all: server client server: server.o g++ -o server server.o client: client.o g++ -o client client.o server.o: server.cpp g++ -c server.cpp client.o:client.cpp g++ -c client.cpp clean: rm -f server client *.o编译链接后, 先启动服务端, 然后在同一机器上启动三个不同的客户端, 此时,在服务端界面, 结果如下:
xxxxxx:~/network> ./server nfds is 1 new sock came, fd is 5 nfds is 1 recv data [this is me] from fd [5] nfds is 1 new sock came, fd is 6 nfds is 1 recv data [this is me] from fd [6] nfds is 1 new sock came, fd is 7 nfds is 1 recv data [this is me] from fd [7]
本文只是epoll的一个简单开始, 比较基础, 后面我们还会进行更多的介绍, 便于深入理解其思路。
相关文章推荐
- 基于linux poll模型的tcp服务器------一个服务器如何与多个客户端进行通信?
- 基于select模型的tcp服务器------一个服务器如何与多个客户端进行通信?
- 基于非阻塞socket的多线程服务器的实现------一个服务器如何与多个客户端进行通信?
- Linux系统tcp模式下服务器与客户端通信(仅限一个客户端)
- java Socket 一个服务器与多个客户端进行通信
- Linux系统编程:客户端-服务器用FIFO进行通信
- Linux下网络编程之自定义协议进行并发多客户端与服务器的通信(多进程处理并发)不足占用资源太多
- 【Linux网络编程实例】实例二:利用TCP协议进行客户端与服务器通信
- 如何使用TCP/IP与服务器进行通信-一个简单的聊天程序
- LINUX下如何创建TCP客户端和服务器,实现通信
- 如何使用TCP/IP与服务器进行通信-一个简单的聊天程序
- 手机客户端和服务器通信时如何安全高效的进行身份验证?
- Linux系统编程:客户端-服务器用FIFO进行通信
- 手机客户端和服务器通信时如何安全高效的进行身份验证
- android与WEB服务器交互时,如何保证在同一个会话Session中通信
- 2012-04-10 16:32 android与WEB服务器交互时,如何保证在同一个会话Session中通信
- Java 的 Socket 服务器和客户端通信的例子 存在一个小问题
- C# winform实现一个服务端和多个客户端进行通信
- 关于客户端发送给epoll模型的服务器,卡send时的一个问题
- 服务器如何跟多个客户端进行通讯呢?