多线程和epoll的结合运用示例

//epoll通过将服务socket if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listener, &ev) < 0) 添加到epoll中
//然后listener监听链接请求,每次监听到一个新的链接就添加到epoll中 epoll_ctl
//如果不是新的链接那么直接创建一个子线程进行业务的处理

#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>
#include <pthread.h>

#define MAXBUF 1024
#define MAXEPOLLSIZE 10000

void pthread_handle_message(void para);
/
setnonblocking - 设置句柄为非阻塞方式
/
int setnonblocking(int sockfd)
{
if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1) {
return -1;
}
return 0;
}

static int count111 = 0;
static time_t oldtime = 0, nowtime = 0;

//------------------------------------------------------------
int main(int argc, char **argv)
{
int listener, new_fd, nfds, n, ret;
struct epoll_event ev;
int kdpfd, curfds;
socklen_t len;
struct sockaddr_in my_addr, their_addr;
unsigned int myport, lisnum;
struct epoll_event events[MAXEPOLLSIZE];
struct rlimit rt;

if (argc>1)
    myport = atoi(argv[1]);
else
    myport = 8006;

if (argc>2)
    lisnum = atoi(argv[2]);
else
    lisnum = 10;

/* 设置每个进程允许打开的最大文件数 */
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");

/*设置socket属性,端口可以重用*/
int opt=SO_REUSEADDR;
setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

/*设置socket为非阻塞模式*/
setnonblocking(listener);

bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = PF_INET;
my_addr.sin_port = htons(myport);
if (argc>3)
    my_addr.sin_addr.s_addr = inet_addr(argv[3]);
else
    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");
        continue;
    }
    /* 处理所有事件 */
    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("有连接来自于: %s:%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
        {
            pthread_attr_t attr;
            pthread_t threadId;

            /*初始化属性值,均设为默认值*/
            pthread_attr_init(&attr);
            pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
            /* 设置线程为分离属性*/
            pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
            if(pthread_create(&threadId,&attr,pthread_handle_message,(void*)&(events[n].data.fd)))
            {
                perror("pthread_creat error!");
                exit(-1);
            }
        }
    }
}
close(listener);
return 0; 

}

void pthread_handle_message(void para)
{
char recvBuf[1024] = {0};
int ret = 999;
int rs = 1;
int socketfd = (int )para;

while(rs)
{
    ret = recv(socketfd,recvBuf,1024,0);// 接受客户端消息

    if(ret < 0)
    {
        //由于是非阻塞的模式,所以当errno为EAGAIN时,表示当前缓冲区已无数据可//读在这里就当作是该次事件已处理过。

        if(errno == EAGAIN)
        {
            printf("EAGAIN\n");
            break;
        }
        else{
            printf("recv error! errno:%d\n", errno);

            close(socketfd);
            break;
        }
    }
    else if(ret == 0)
    {
        // 这里表示对端的socket已正常关闭.
        rs = 0;
    }
    if(ret == sizeof(recvBuf))
        rs = 1; // 需要再次读取
    else
        rs = 0;
}

if(ret>0){
    count111 ++;
    struct tm *today;
    time_t ltime;
    time( &nowtime );

    if(nowtime != oldtime){
        printf("%d\n", count111);
        oldtime = nowtime;
        count111 = 0;
    }

    char buf[1000] = {0};
    sprintf(buf,"HTTP/1.0 200 OK\r\nContent-type: text/plain\r\n\r\n%s","Hello world!\n");
    send(socketfd,buf, strlen(buf),0);
}
close(socketfd);

}

原文地址:https://blog.51cto.com/wenxuehui/2433934

时间: 2024-11-08 11:21:51

多线程和epoll的结合运用示例的相关文章

C++实现一个多线程同步方式的协同工作程序示例

多线程并发程序与协同程序其实是不同的概念.多线程并发是多个执行序同时运行,而协同程序是多个执行序列相互协作,同一时刻只有一个执行序列.今天想到的是将两者结合起来,拿现实生活中的例子来说,假设一个班级有100个学生,一个老师要批改100个学生的作业,有时老师太忙或者赶时间会叫几个同学帮忙批改,等所有同学都批改完后都交到老师手中,老师在下次上课的时候将作业本一起发给班上的学生....其实在并发编程的时候也可以借鉴这一个思想和模式,特别是网络服务器开发的过程中,并发与协同经常出现,于是今天写了一个简单

java多线程中死锁情况的一个示例

下面是死锁情况的一个示例代码 package com.qust.demo.money; class A { public synchronized void foo(B b) { System.out.println(Thread.currentThread().getName() + " 进入A的foo"); try { Thread.sleep(200); } catch (InterruptedException ex) { ex.printStackTrace(); } Sys

Java并发和多线程1:并发框架基本示例.txt

Executor框架是指java 5中引入的一系列并发库中与executor相关的一些功能类,其中包括ThreadPool,Executor,Executors,ExecutorService,CompletionService,Future,Callable等. 并发编程的一种编程方式是把任务拆分为一系列的小任务,即Runnable,然后在提交给一个Executor执行,Executor.execute(Runnalbe) .Executor在执行时使用内部的线程池完成操作.一.创建线程池Ex

多线程中的条件线程简单示例

1.原理:理解的条件线程最常见的用法就是两个线程同时对一个队列进行处理,比如一个线程负责在队列未满的时候插入item,另外一个线程负责在队列非空时取出item,条件线程涉及4个线程相关函数,pthread_mutex_lock.pthread_mutex_unlock.pthread_cond_wait.pthread_cond_signal,其中pthread_mutex_lock负责对线程加锁,以免其他线程同时对共享资源(比如本例中的int cond_num)进行修改,pthread_mut

python的多线程、多进程代码示例

多线程有两种方式:thread和threading 这里应用的场景是map数据分多线程.进度写入codis的示例 这是thread的示例:thread的主进程不会等待线程 import thread,math,threading,multiprocessing,os,time def writeToCodis(prefix,key_list,result_map): # client = BfdCodis("xxx", ) begin = int(time.time()) for ke

c#使用多线程的几种方式示例详解

本文转载自:http://www.jb51.net/article/46234.htm 本文章主要介绍了c#使用多线程的几种方式,通过示例学习c#的多线程使用方式,大家参考使用吧 (1)不需要传递参数,也不需要返回参数 ThreadStart是一个委托,这个委托的定义为void ThreadStart(),没有参数与返回值. 复制代码 代码如下: class Program { static void Main(string[] args) { for (int i = 0; i < 30; i

【转】Java多线程操作局部变量与全局变量

原文网址:http://blog.csdn.net/undoner/article/details/12849661 在这篇文章里,我们首先阐述什么是同步,不同步有什么问题,然后讨论可以采取哪些措施控制同步,接下来我们会仿照回顾网络通信时那样,构建一个服务器端的“线程池”,JDK为我们提供了一个很大的concurrent工具包,最后我们会对里面的内容进行探索. 为什么要线程同步? 说到线程同步,大部分情况下, 我们是在针对“单对象多线程”的情况进行讨论,一般会将其分成两部分,一部分是关于“共享变

09、多线程(一) -- 基本概念

1.1.多线程基本使用 1.线程的创建方式 多线程的创建有两种方式,分别如下: 继承 继承Thread类,并重写run方法,将需要多线程的代码放入run方法中. 通过Thread的子类的引用调用start()方法来开启线程. 实现 定义类实现Runnable接口,覆盖Runnable接口中的run方法. 通过Thread类建立线程对象. 将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数. 调用Thread类的star方法开启线程并调用Runnable接口子类的run方法

【转】多线程编程指南

原文网址:http://docs.oracle.com/cd/E19253-01/819-7051/index.html 多线程编程指南 Book Information 索引 前言 第 1 章 多线程基础介绍 第 2 章 基本线程编程 第 3 章 线程属性 第 4 章 用同步对象编程 第 5 章 使用 Solaris 软件编程 第 6 章 安全和不安全的接口 第 7 章 编译和调试 第 8 章 Solaris 线程编程 第 9 章 编程原则 附录 A 样例应用程序:多线程 grep 附录 B