服务器端编程实例(二 单进程并发_IO多路复用)
来源:互联网 发布:鄂维南 大数据 编辑:程序博客网 时间:2024/06/13 15:56
2.1)select
函数语法:
/* According to POSIX 1003.1-2001 */
#include <sys/select.h>
/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
int pselect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t
*sigmask);
FD_CLR(int fd, fd_set *set);
FD_ISSET(int fd, fd_set *set);
FD_SET(int fd, fd_set *set);
FD_ZERO(fd_set *set);
DESCRIPTION
The functions select and pselect wait for a number of file descriptors to change status.
RETURN VALUE
On success, select and pselect return the number of descriptors contained in the descriptor sets, which may be zero if the timeout expires before anything interesting happens. On error, -1 is returned, and errno is set appropriately; the sets and timeout become undefined, so do not rely on their contents after an error.
示例:
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int main (void)
{
fd_set rfds;
struct timeval tv;
int retval;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO (&rfds);
FD_SET (0, &rfds);
FD_SET (1, &rfds);
FD_SET (2, &rfds);
FD_SET (4, &rfds);
/* Wait up to five seconds. */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select (2, &rfds, NULL, NULL, &tv);
if (retval == -1)
perror ("select()");
else if (retval)
{
printf ("Data is available now./n");
printf( "retval=%d/n",retval);
}
/* FD_ISSET(0, &rfds) will be true. */
else
printf ("No data within five seconds./n");
return 0;
}
2.2)epoll
SYNOPSIS
#include <sys/epoll.h>
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
int epoll_create(int size)
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout)
示例:
#include <iostream>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#define MAXLINE 10
#define OPEN_MAX 100
#define LISTENQ 20
#define SERV_PORT 5555
#define INFTIM 1000
void setnonblocking(int sock)
{
int opts;
opts = fcntl(sock, F_GETFL);
if (opts < 0)
{
perror("fcntl(sock, GETFL)");
exit(1);
}
opts = opts|O_NONBLOCK;
if (fcntl(sock, F_SETFL, opts) < 0)
{
perror("fcntl(sock, SETFL, opts)");
exit(1);
}
}
int main()
{
int i, maxi, listenfd, connfd, sockfd, epfd, nfds;
ssize_t n = 0;
char line[MAXLINE];
int l_sinSize = 0;
l_sinSize = sizeof(struct sockaddr);
//声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件
struct epoll_event ev, events[20];//--------------------
//生成用于处理accept的epoll专用的文件描述符
epfd = epoll_create(256);//-----------------------------
struct sockaddr_in clientaddr;
struct sockaddr_in serveraddr;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
//把socket设置为非阻塞方式
setnonblocking(listenfd);//-----------------------------
//设置与要处理的事件相关的文件描述符
ev.data.fd = listenfd;//--------------------------------
//设置要处理的事件类型
ev.events = EPOLLIN|EPOLLET;//--------------------------
//注册epoll事件
epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev);//---------------------
bzero(&serveraddr, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons(SERV_PORT);
bind(listenfd, (struct sockaddr *)(&serveraddr), sizeof(struct sockaddr));
listen(listenfd, LISTENQ);
maxi = 0;
for ( ; ; ) {
//等待epoll事件的发生
nfds=epoll_wait(epfd,events,20,500);//---------------------------
//处理所发生的所有事件
for (i = 0; i < nfds; ++i)
{
if (events[i].data.fd == listenfd)
{
connfd = accept(listenfd, (struct sockaddr *)(&clientaddr), (socklen_t *)&l_sinSize);//------------
if (connfd < 0)
{
perror("connfd < 0");
exit(1);
}
setnonblocking(connfd);
char* str = inet_ntoa(clientaddr.sin_addr);
std::cout<<"connect from "<<str<<std::endl;
//设置用于读操作的文件描述符
ev.data.fd = connfd;
//设置用于注测的读操作事件
ev.events = EPOLLIN|EPOLLET;
//注册ev
epoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &ev);
}
else if (events[i].events&EPOLLIN)
{
if ((sockfd = events[i].data.fd) < 0)
{
continue;
}
if ((n = read(sockfd, line, MAXLINE)) < 0)
{
if (errno == ECONNRESET)
{
close(sockfd);
events[i].data.fd = -1;
}
else
{
std::cout<<"readline error"<<std::endl;
}
}
else if (n == 0)
{
close(sockfd);
events[i].data.fd = -1;
}
//设置用于写操作的文件描述符
ev.data.fd = sockfd;
//设置用于注测的写操作事件
ev.events = EPOLLOUT|EPOLLET;
//修改sockfd上要处理的事件为EPOLLOUT
epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
}
else if(events[i].events&EPOLLOUT)
{
sockfd = events[i].data.fd;
ssize_t l_writeSize = write(sockfd, line, n);
std::cout<<"write "<<l_writeSize<<std::endl;
//设置用于读操作的文件描述符
ev.data.fd = sockfd;
//设置用于注测的读操作事件
ev.events = EPOLLIN|EPOLLET;
//修改sockfd上要处理的事件为EPOLIN
epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
}
}
}
}
- 服务器端编程实例(二 单进程并发_IO多路复用)
- 服务器端编程实例(三 多进程并发)
- 网络通讯中服务器端编程实例(一 单进程循环)
- 服务器端编程实例(四 多线程并发)
- 小试牛刀TCP 网络编程模式,单线程多路复用实例
- linux下一个单进程并发服务器的实例 使用select
- Linux下一个单进程并发服务器的实例 使用select
- 实现并发多进程服务器端
- Erlang/OTP并发编程实例(二)
- java 并发编程(二)之synchronized实例
- Linux并发服务器编程之IO多路复用
- 服务器端编程完整实例
- 网络编程(6)单进程多线程并发服务器实现
- Java网络编程-IO多路复用(单线程)
- linux 网络编程---->多路复用:select实例!
- linux 网络编程---->多路复用:select实例!
- 《Unix环境高级编程》:单实例守护进程的实现
- 《Unix环境高级编程》:单实例守护进程的实现
- Synchronization Context
- File 对象的相关操作和访问(2)
- 开博1月庆
- OWC使用ASPNET的程序集作数据源
- ACM会用到的一点数学知识
- 服务器端编程实例(二 单进程并发_IO多路复用)
- File 对象的相关操作和访问(3)
- 在 Visual Basic .NET 和 Visual C# .NET 中创建控件数组
- 编程之道 Translated By Geoffrey James
- MSDN放出简体中文版Windows Vista RTM(包含下载)
- 对c/c++可变参数表的深层探索
- LumaQQ2006的安装
- 微软有内鬼?还是黑客太高强?
- 一黑客侵入他人电脑 窥视其隐私敲诈14万元