`
yuanyu5237
  • 浏览: 162747 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

简单epoll服务器

 
阅读更多

  学习

#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服务器

    本文将深入探讨epoll的工作原理、优势以及如何在C++中实现一个简单的epoll服务器。 ### 一、epoll概述 epoll是Linux内核提供的一个接口,它通过事件驱动的方式管理多个文件描述符。与传统的轮询方式相比,epoll...

    epoll 的并发服务器

    这个示例展示了如何使用`epoll`构建一个简单的并发服务器。实际应用中,还需要考虑错误处理、多线程或多进程并发处理、资源管理等问题。 总结来说,`epoll`是Linux下开发高性能并发服务器的关键技术,通过高效地...

    Linux下Epoll+线程池的简单Web服务器

    本文将深入探讨如何在Linux环境下使用Epoll和线程池技术构建一个简单的Web服务器。这个Web服务器的实现是基于Linux内核提供的异步I/O模型,Epoll,以及线程池策略,以优化系统资源的使用和提高并发性能。 首先,让...

    C语言长连接服务器Demo(epoll非阻塞)

    一个简单的C语言epoll长连接服务器Demo的流程可能如下: 1. 初始化epoll实例:调用epoll_create()创建epoll句柄。 2. 创建监听套接字:socket()、bind()、listen(),然后将监听套接字添加到epoll实例,设置为边缘...

    Linux下epoll实现简易聊天

    这个“Linux下epoll实现简易聊天”项目提供了使用epoll实现简单QQ聊天应用的源代码,旨在帮助开发者了解如何在实际场景中应用epoll。 epoll的核心概念包括以下几点: 1. **I/O多路复用**:I/O多路复用允许单个进程...

    使用epoll开发python服务器

    对于初学者,可以通过编写简单的客户端程序来测试epoll服务器。客户端发送请求并接收响应,以此验证服务器的正确性。Python的`socket`模块可以用来创建这样的客户端。 ```python import socket client = socket....

    linux epoll多线程编程 例子

    线程池 + epoll 的简单实现通常包括以下步骤: 1. 创建epoll实例:使用`epoll_create()`函数创建一个epoll实例,返回一个epoll文件描述符。 2. 注册文件描述符:使用`epoll_ctl()`函数将需要监听的文件描述符(如...

    Linux网络编程(四)——epoll+多线程实现简单的聊天(linux 服务器端 windows客户端)

    在本篇中,我们将深入探讨如何使用Linux网络编程技术,特别是epoll和多线程机制,来构建一个简单的跨平台聊天应用。这个应用涉及到Linux服务器端和Windows客户端的交互,让我们逐一解析其中的关键知识点。 首先,`...

    通过IE访问linux编写的服务器,epoll

    本程序利用`epoll`技术编写了一个简单的服务器,允许用户通过Internet Explorer(IE)浏览器进行访问。接下来,我们将深入探讨`epoll`的工作原理及其在Linux服务器编程中的应用。 `epoll`是Linux内核提供的I/O多路...

    python-epoll-examples

    在压缩包中的"python-epoll-examples"可能包含了各种场景下的应用实例,如简单的TCP服务器、多客户端服务等。通过分析和运行这些示例,你可以更深入地理解epoll的工作原理和用法。 示例代码通常会展示如何创建...

    linux epoll 代码例子

    下面是一个简单的epoll使用代码示例: ```c #include &lt;sys/epoll.h&gt; #include #include #include int main() { int epfd = epoll_create(1); // 创建epoll实例 if (epfd == -1) { perror("epoll_create"); ...

    linux_C++ tcpEpoll 的简单实现

    本教程将介绍如何使用C++在Linux环境下实现基于`epoll`的TCP服务器。 首先,我们需要理解`epoll`的工作原理。`epoll`采用了“事件”的概念,通过`epoll_create`函数创建一个`epoll`实例,然后使用`epoll_ctl`添加感...

    epoll服务示例(suse10下编译运行无问题)

    给定的 epoll 服务示例是一个简单的 TCP 服务器端示例,使用 epoll 机制来处理客户端的连接请求。 服务端代码分析 服务端代码中首先包含了一系列的头文件,包括"netinet/in.h"、"sys/types.h" 等,用于提供 socket...

    IO多路复用之epoll实例

    Qt库提供了QSocketNotifier类,可以与epoll接口进行交互,使得在Qt应用中使用epoll变得简单。 在实际应用中,epoll通常用于服务器端,特别是高并发的网络服务,例如Web服务器、数据库服务器等。通过epoll,这些...

    epoll文档.zip

    在高并发服务器开发中,epoll是实现高性能网络编程的重要工具。下面将详细介绍epoll的优越性、工作原理、使用方法以及实例应用。 ### 一、epoll的优越性 1. **效率提升**:epoll采用“事件驱动”的方式,相比于...

    epoll 详细介绍

    当连接数量较少时,使用阻塞模式或多线程可能更为简单,但在大规模并发场景下,`epoll`是更好的选择。正确理解和使用`epoll`的ET模式,能够有效地处理大量并发连接,提高服务器的响应速度和吞吐量。

    epoll原理与实现

    例如,在Web服务器、数据库服务器、消息队列等场景中,合理利用`epoll`可以显著提高系统的并发能力和响应速度。 1. **高性能Web服务器**:通过`epoll`监控大量的客户端连接,并在每个连接上高效地处理读写事件。 2....

    使用epoll 和线程池实现简单的图片浏览服务器.zip

    在本课程设计中,我们将探讨如何使用C语言结合epoll事件多路复用技术和线程池来构建一个简单的图片浏览服务器。这个项目旨在帮助学生理解网络编程中的高性能服务器设计原则,特别是针对高并发场景下的优化策略。 ...

    linux epoll例子

    在给定的压缩包文件"sechat"中,很可能包含了一个使用epoll实现的简单聊天服务器或者客户端的示例代码。"sechat"这个名字可能暗示这是一个基于socket的聊天应用,其中epoll用于处理多个客户端连接的并发事件。 在...

Global site tag (gtag.js) - Google Analytics