`
Michaelmatrix
  • 浏览: 208819 次
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

使用epoll实现客户端UDP并发

 
阅读更多

网络程序为了支持并发,可以采用select,多线程等技术.
但是对于select,readhat linux系统只支持最大1024个描述符.
因此要想同时并发超过1024,就无法使用select模式.
而使用多线程,并发数达到1000时将严重影响系统的性能.

而使用epoll可以避免以上的缺陷.
下面是一个使用epoll实现客户端UDP并发.是我为写压力测试程序而写的.
发送使用一个独立的线程,接收使用epoll调用.

在程序开始要先设置系统能打开的最大描述符限制.即setrlimt调用.

在linux readhat enterprise 4环境下测试通过。其它环境我没测过。

g++ -oudp_epoll_c udp_epoll_c.cpp -lpthread

CODE:


/***************************************************************************
file: udp_epoll_c.cpp
-------------------
begin : 2006/01/17
copyright : (C) 2005 by 张荐林
email : zhangjianlin_8 at 126.com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify*
* it under the terms of the GNU General Public License as published by*
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/


#include <errno.h>
#include <iostream>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string>
#include <sys/resource.h>
#include <pthread.h>
#include <vector>
using namespace std;
int Read(int fd,void *buffer,unsigned int length)
{
unsigned int nleft;
int nread;
char *ptr;
ptr = (char *)buffer;
nleft = length;
while(nleft > 0)
{
if((nread = read(fd, ptr, nleft))< 0)
{
if(errno == EINTR)
nread = 0;
else
return -1;
}
else if(nread == 0)
{
break;
}
nleft -= nread;
ptr += nread;
}
return length - nleft;
}

int Write(int fd,const void *buffer,unsigned int length)
{
unsigned int nleft;
int nwritten;
const char *ptr;
ptr = (const char *)buffer;
nleft = length;
while(nleft > 0)
{
if((nwritten = write(fd, ptr, nleft))<=0)
{
if(errno == EINTR)
nwritten=0;
else
return -1;
}
nleft -= nwritten;
ptr += nwritten;
}
return length;
}
int CreateThread(void *(*start_routine)(void *), void *arg = NULL, pthread_t *thread = NULL, pthread_attr_t *pAttr = NULL)
{
pthread_attr_t thr_attr;
if(pAttr == NULL)
{
pAttr = &thr_attr;
pthread_attr_init(pAttr);
pthread_attr_setstacksize(pAttr, 1024 * 1024);// 1 M的堆栈
pthread_attr_setdetachstate(pAttr,PTHREAD_CREATE_DETACHED);
}
pthread_t tid;
if(thread == NULL)
{
thread = &tid;
}
int r = pthread_create(thread, pAttr, start_routine, arg);
pthread_attr_destroy(pAttr);
return r;
}

static int SetRLimit()
{
struct rlimit rlim;
rlim.rlim_cur = 20480;
rlim.rlim_max = 20480;
if (setrlimit(RLIMIT_NOFILE, &rlim) != 0)
{
perror("setrlimit");
}
else
{
printf("setrlimit ok/n");
}
return 0;
}

int setnonblocking(int sock)
{
int opts;
opts=fcntl(sock,F_GETFL);
if(opts<0)
{
return -1;
}
opts = opts|O_NONBLOCK;
if(fcntl(sock,F_SETFL,opts)<0)
{
return -1;
}
return 0;
}

int ConnectToUdperver(const char *host, unsigned short port)
{
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if(sock < 0)
{
perror("socket");
return -1;
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(host);

if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
perror("bind");
close(sock);
return -1;
}
return sock;
}

void *SendThread(void *arg)
{
vector<int> sockets;
sockets = *((vector<int> *)arg);

int n = 0;
char data[1024];
int i = 0;
while(1)
{
for(vector<int>::iterator itr = sockets.begin(), last = sockets.end(); itr != last; ++itr)
{
sprintf(data, "test data %d/n", i++);
n = Write(*itr, "hello", 5);
printf("socket %d write to server[ret = %d]:%s",*itr, n, data);
}
sleep(1);
}
}

int main(int argc, char **argv)
{
SetRLimit();
printf("FD_SETSIZE= %d/n", FD_SETSIZE);
if (argc != 3)
{
printf("usage: %s <IPaddress> <PORT>/n", argv[0]);
return 1;
}

int epfd = epoll_create(20480);
if(epfd < 0)
{
perror("epoll_create");
return 1;
}
struct epoll_event event;
struct epoll_event ev[20480];
vector<int> sockets;
for(int i = 0; i < 3000; i++)
{
int sockfd = ConnectToUdperver(argv[1], (unsigned short)(atoi(argv[2])));
if(sockfd < 0)
{
printf("Cannot connect udp server %s %s/n", argv[1], argv[2]);
return 1;
}

sockets.push_back(sockfd);
setnonblocking(sockfd);
event.data.fd = sockfd;
event.events = EPOLLIN|EPOLLET;
if(0 != epoll_ctl(epfd,EPOLL_CTL_ADD,sockfd,&event))
{
perror("epoll_ctl");
}
}
if(0 != CreateThread(SendThread, (void *)&sockets))
{
perror("CreateThread");
return 2;
}
int nfds = 0;
while(1)
{
nfds=epoll_wait(epfd,ev,20480,500);
if(nfds < 0)
{
perror("epoll_wait");
break;
}
else if(nfds == 0)
{
printf("epoll_wait timeout!/n");
continue;
}
for(int i = 0; i < nfds; i++)
{
if(ev[i].events & EPOLLIN)
{
printf("can read for %d now/n", ev[i].data.fd);
char data[1024] = {0};
int n = read(ev[i].data.fd, data, sizeof(data));
printf("Received %d bytes from server!/n", n);
}
}
}
for(vector<int>::iterator itr = sockets.begin(), last = sockets.end(); itr != last; itr++)
{
close(*itr);
}
close(epfd);
return 0;
}

分享到:
评论

相关推荐

    python网络编程

    课程介绍 ⽹络概述、udp ⽹络通信概述 tcp/ip简介 端⼝ ...并发服务器、HTTP协议 单进程服务器 多进程服务器 多线程服务器 单进程服务器-⾮堵塞模式 单进程服务器-select版 单进程服务器-epoll版 多任务实现-协程

    基于C++11线程池技术简单易用的轻量级网络编程框架源码.zip

    使用epoll+线程池+异步网络IO模式开发,并发性能优越。 代码经过大量的稳定性、性能测试,可满足商用服务器项目。 支持linux、macos、ios、android、windows平台 特性: 网络库 tcp/udp客户端,接口简单易用并且是...

    ZLToolKit:一个基于C++11的轻量级网络框架,基于线程池技术可以实现大并发网络IO

    使用epoll+线程池+异步网络IO模式开发,并发性能优越。代码经过大量的稳定性、性能测试,可满足商用服务器项目。支持linux、macos、ios、android、windows平台了解更多:特性网络库tcp/udp客户端,接口简单易用并且是...

    linux C语言 网络编程教程及源码

    21、Linux网络编程——tcp高效并发服务器(epoll实现) 二、网络底层编程(黑客模式) 1、Linux网络编程1——啥叫原始套接字 2、Linux网络编程2——原始套接字编程 3、Linux网络编程3——原始套接字实例:MAC头分析 ...

    安卓毕业设计app源码-mushroom:C语言高性能跨平台socket库,支持TCP,UDP和IPv6,支持平台:linux,macos,w

    mushroom支持TCP、UDP通信,让客户端非常容易创建并发网络链接,可以让手机快速创建上万条链接,甚至可以让手机作为服务器,被上万客户端连接。 mushroom还有另外一个分支mushroom-kcp,mushroom-kcp在UDP的基础上,...

    HP-Socket:高性能TCPUDPHTTP通信组件

    服务器基于IOCP / EPOLL通信模型,结合内存池,私有堆等技术,实现了高效的内存管理,以支持大规模和高并发通信场景。 代理代理组件本质上是一个多客户端组件,它使用与服务器组件相同的技术体系结构。 Agent组件...

    HP-Socket通信框架 v5.7.3

    为您提供HP-Socket通信框架下载,HP-Socket 是一套通用的高性能 TCP/UDP/HTTP 通信框架,包含服务端...特点:Server基于IOCP / EPOLL通信模型,并结合缓存池、私有堆等技术实现高效内存管理,支持超大规模、高并发通

    HP-Socket通信框架-其他

    基于IOCP / EPOLL通信模型,并结合缓存池、私有堆等技术实现高效内存管理,支持超大规模、高并发通信场景。 Agent Agent组件实质上是Multi-Client组件,与Server组件采用相同的技术架构。一个Agent组件对象可同时...

    python入门到高级全栈工程师培训 第3期 附课件代码

    09 select与epoll的实现区别 第36章 01 异步IO 02 selectors模块介绍 03 selectors模块应用 04 作业介绍 第37章 01 selctors实现文件上传与下载 02 html的介绍 03 html文档树的概念 04 meta标签以及一些基本标签...

    Linux高性能服务器编程

    聊天室程序 9.6.1 客户端 9.6.2 服务器 9.7 IO复用的高级应用三:同时处理TCP和UDP服务 9.8 超级服务xinetd 9.8.1 xinetd配置文件 9.8.2 xinetd工作流程 第10章 信号 10.1 Linux信号概述 10.1.1 发送信号 ...

    bl-api-cloud,可扩展轻云服务端框架-易语言

    其Server 组件:基于IOCP / EPOLL通信模型,并结合缓存池、私有堆等技术实现高效内存管理,支持超大规模、高并发通信场景。 应用程序能够根据不同的容量要求、通信规模和资源状况等现实场景调整 HP-Socket 的各项...

Global site tag (gtag.js) - Google Analytics