学习
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/time.h>
#include <sys/resource.h>
#define MAXBUF 1024
#define MAXEPOLLSIZE 10000
/*
setnonblocking - 设置句柄为非阻塞方式
*/
int setnonblocking(int sockfd)
{
if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1)
{
return -1;
}
return 0;
}
/*
handle_message - 处理每个 socket 上的消息收发
*/
int handle_message(int new_fd)
{
char buf[MAXBUF + 1];
int len;
/* 开始处理每个新连接上的数据收发 */
bzero(buf, MAXBUF + 1);
/* 接收客户端的消息 */
len = recv(new_fd, buf, MAXBUF, 0);
if (len > 0)
{
printf("%d接收消息成功:'%s',共%d个字节的数据\n",
new_fd, buf, len);
send(new_fd,buf,len,0);
}
else
{
if (len < 0)
printf
("消息接收失败!错误代码是%d,错误信息是'%s'\n",
errno, strerror(errno));
close(new_fd);
return -1;
}
/* 处理每个新连接上的数据收发结束 */
return len;
}
int main(int argc, char **argv)
{
int listener, new_fd, kdpfd, nfds, n, ret, curfds;
socklen_t len;
struct sockaddr_in my_addr, their_addr;
unsigned int myport, lisnum;
struct epoll_event ev;
struct epoll_event events[MAXEPOLLSIZE];
struct rlimit rt;
myport = 5000;
lisnum = 2;
/* 设置每个进程允许打开的最大文件数 */
rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;
if (setrlimit(RLIMIT_NOFILE, &rt) == -1)
{
perror("setrlimit");
exit(1);
}
else
{
printf("设置系统资源参数成功!\n");
}
/* 开启 socket 监听 */
if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
exit(1);
}
else
{
printf("socket 创建成功!\n");
}
setnonblocking(listener);
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = PF_INET;
my_addr.sin_port = htons(myport);
my_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(listener, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1)
{
perror("bind");
exit(1);
}
else
{
printf("IP 地址和端口绑定成功\n");
}
if (listen(listener, lisnum) == -1)
{
perror("listen");
exit(1);
}
else
{
printf("开启服务成功!\n");
}
/* 创建 epoll 句柄,把监听 socket 加入到 epoll 集合里 */
kdpfd = epoll_create(MAXEPOLLSIZE);
len = sizeof(struct sockaddr_in);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = listener;
if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listener, &ev) < 0)
{
fprintf(stderr, "epoll set insertion error: fd=%d\n", listener);
return -1;
}
else
{
printf("监听 socket 加入 epoll 成功!\n");
}
curfds = 1;
while (1)
{
/* 等待有事件发生 */
nfds = epoll_wait(kdpfd, events, curfds, -1);
if (nfds == -1)
{
perror("epoll_wait");
break;
}
/* 处理所有事件 */
for (n = 0; n < nfds; ++n)
{
if (events[n].data.fd == listener)
{
new_fd = accept(listener, (struct sockaddr *) &their_addr,&len);
if (new_fd < 0)
{
perror("accept");
continue;
}
else
{
printf("有连接来自于: %d:%d, 分配的 socket 为:%d\n",
inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port), new_fd);
}
setnonblocking(new_fd);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = new_fd;
if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, new_fd, &ev) < 0)
{
fprintf(stderr, "把 socket '%d' 加入 epoll 失败!%s\n",
new_fd, strerror(errno));
return -1;
}
curfds++;
}
else
{
ret = handle_message(events[n].data.fd);
if (ret < 1 && errno != 11)
{
epoll_ctl(kdpfd, EPOLL_CTL_DEL, events[n].data.fd,&ev);
curfds--;
}
}
}
}
close(listener);
return 0;
}
gcc epollserver.c
分享到:
相关推荐
本文将深入探讨epoll的工作原理、优势以及如何在C++中实现一个简单的epoll服务器。 ### 一、epoll概述 epoll是Linux内核提供的一个接口,它通过事件驱动的方式管理多个文件描述符。与传统的轮询方式相比,epoll...
这个示例展示了如何使用`epoll`构建一个简单的并发服务器。实际应用中,还需要考虑错误处理、多线程或多进程并发处理、资源管理等问题。 总结来说,`epoll`是Linux下开发高性能并发服务器的关键技术,通过高效地...
本文将深入探讨如何在Linux环境下使用Epoll和线程池技术构建一个简单的Web服务器。这个Web服务器的实现是基于Linux内核提供的异步I/O模型,Epoll,以及线程池策略,以优化系统资源的使用和提高并发性能。 首先,让...
一个简单的C语言epoll长连接服务器Demo的流程可能如下: 1. 初始化epoll实例:调用epoll_create()创建epoll句柄。 2. 创建监听套接字:socket()、bind()、listen(),然后将监听套接字添加到epoll实例,设置为边缘...
这个“Linux下epoll实现简易聊天”项目提供了使用epoll实现简单QQ聊天应用的源代码,旨在帮助开发者了解如何在实际场景中应用epoll。 epoll的核心概念包括以下几点: 1. **I/O多路复用**:I/O多路复用允许单个进程...
对于初学者,可以通过编写简单的客户端程序来测试epoll服务器。客户端发送请求并接收响应,以此验证服务器的正确性。Python的`socket`模块可以用来创建这样的客户端。 ```python import socket client = socket....
线程池 + epoll 的简单实现通常包括以下步骤: 1. 创建epoll实例:使用`epoll_create()`函数创建一个epoll实例,返回一个epoll文件描述符。 2. 注册文件描述符:使用`epoll_ctl()`函数将需要监听的文件描述符(如...
在本篇中,我们将深入探讨如何使用Linux网络编程技术,特别是epoll和多线程机制,来构建一个简单的跨平台聊天应用。这个应用涉及到Linux服务器端和Windows客户端的交互,让我们逐一解析其中的关键知识点。 首先,`...
本程序利用`epoll`技术编写了一个简单的服务器,允许用户通过Internet Explorer(IE)浏览器进行访问。接下来,我们将深入探讨`epoll`的工作原理及其在Linux服务器编程中的应用。 `epoll`是Linux内核提供的I/O多路...
在压缩包中的"python-epoll-examples"可能包含了各种场景下的应用实例,如简单的TCP服务器、多客户端服务等。通过分析和运行这些示例,你可以更深入地理解epoll的工作原理和用法。 示例代码通常会展示如何创建...
下面是一个简单的epoll使用代码示例: ```c #include <sys/epoll.h> #include #include #include int main() { int epfd = epoll_create(1); // 创建epoll实例 if (epfd == -1) { perror("epoll_create"); ...
本教程将介绍如何使用C++在Linux环境下实现基于`epoll`的TCP服务器。 首先,我们需要理解`epoll`的工作原理。`epoll`采用了“事件”的概念,通过`epoll_create`函数创建一个`epoll`实例,然后使用`epoll_ctl`添加感...
给定的 epoll 服务示例是一个简单的 TCP 服务器端示例,使用 epoll 机制来处理客户端的连接请求。 服务端代码分析 服务端代码中首先包含了一系列的头文件,包括"netinet/in.h"、"sys/types.h" 等,用于提供 socket...
Qt库提供了QSocketNotifier类,可以与epoll接口进行交互,使得在Qt应用中使用epoll变得简单。 在实际应用中,epoll通常用于服务器端,特别是高并发的网络服务,例如Web服务器、数据库服务器等。通过epoll,这些...
在高并发服务器开发中,epoll是实现高性能网络编程的重要工具。下面将详细介绍epoll的优越性、工作原理、使用方法以及实例应用。 ### 一、epoll的优越性 1. **效率提升**:epoll采用“事件驱动”的方式,相比于...
当连接数量较少时,使用阻塞模式或多线程可能更为简单,但在大规模并发场景下,`epoll`是更好的选择。正确理解和使用`epoll`的ET模式,能够有效地处理大量并发连接,提高服务器的响应速度和吞吐量。
例如,在Web服务器、数据库服务器、消息队列等场景中,合理利用`epoll`可以显著提高系统的并发能力和响应速度。 1. **高性能Web服务器**:通过`epoll`监控大量的客户端连接,并在每个连接上高效地处理读写事件。 2....
在本课程设计中,我们将探讨如何使用C语言结合epoll事件多路复用技术和线程池来构建一个简单的图片浏览服务器。这个项目旨在帮助学生理解网络编程中的高性能服务器设计原则,特别是针对高并发场景下的优化策略。 ...
在给定的压缩包文件"sechat"中,很可能包含了一个使用epoll实现的简单聊天服务器或者客户端的示例代码。"sechat"这个名字可能暗示这是一个基于socket的聊天应用,其中epoll用于处理多个客户端连接的并发事件。 在...