linux+socket+定时器,Linux网络编程--定时器的学习和使用

#include #include "lst_timer.h"

#define FD_LIMIT 65535

#define MAX_EVENT_NUMBER 1024

#define TIMESLOT 5

static int pipefd[2];

static sort_timer_lst timer_lst;

static int epollfd = 0;

int setnonblocking( int fd )

{

int old_option = fcntl( fd, F_GETFL );

int new_option = old_option | O_NONBLOCK;

fcntl( fd, F_SETFL, new_option );

return old_option;

}

void addfd( int epollfd, int fd )

{

epoll_event event;

event.data.fd = fd;

event.events = EPOLLIN | EPOLLET;

epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event );

setnonblocking( fd );

}

void sig_handler( int sig )

{

int save_errno = errno;

int msg = sig;

send( pipefd[1], ( char* )&msg, 1, 0 );//向写端发送信号值

errno = save_errno;

}

void addsig( int sig )

{

struct sigaction sa;

memset( &sa, '\0', sizeof( sa ) );

sa.sa_handler = sig_handler;

sa.sa_flags |= SA_RESTART;

sigfillset( &sa.sa_mask );

assert( sigaction( sig, &sa, NULL ) != -1 );//发送信号

}

void timer_handler()

{

timer_lst.tick();

alarm( TIMESLOT );

}

void cb_func( client_data* user_data )//定时器容器的元素之一:函数指针对应的函数

{

epoll_ctl( epollfd, EPOLL_CTL_DEL, user_data->sockfd, 0 );

assert( user_data );

close( user_data->sockfd );

printf( "close fd %d\n", user_data->sockfd );

}

int main( int argc, char* argv[] )

{

if( argc <= 2 )

{

printf( "usage: %s ip_address port_number\n", basename( argv[0] ) );

return 1;

}

const char* ip = argv[1];

int port = atoi( argv[2] );

int ret = 0;

struct sockaddr_in address;

bzero( &address, sizeof( address ) );

address.sin_family = AF_INET;

inet_pton( AF_INET, ip, &address.sin_addr );

address.sin_port = htons( port );

int listenfd = socket( PF_INET, SOCK_STREAM, 0 );

assert( listenfd >= 0 );

ret = bind( listenfd, ( struct sockaddr* )&address, sizeof( address ) );

assert( ret != -1 );

ret = listen( listenfd, 5 );

assert( ret != -1 );

epoll_event events[ MAX_EVENT_NUMBER ];

int epollfd = epoll_create( 5 );

assert( epollfd != -1 );

addfd( epollfd, listenfd );

ret = socketpair( PF_UNIX, SOCK_STREAM, 0, pipefd );//创建双工管道

assert( ret != -1 );

setnonblocking( pipefd[1] );

addfd( epollfd, pipefd[0] );//epoll监控fd[0]描述符(读端)

// add all the interesting signals here

addsig( SIGALRM );

addsig( SIGTERM );

bool stop_server = false;

client_data* users = new client_data[FD_LIMIT];

bool timeout = false;

alarm( TIMESLOT );

while( !stop_server )

{

int number = epoll_wait( epollfd, events, MAX_EVENT_NUMBER, -1 );

if ( ( number < 0 ) && ( errno != EINTR ) )

{

printf( "epoll failure\n" );

break;

}

for ( int i = 0; i < number; i++ )

{

int sockfd = events[i].data.fd;

if( sockfd == listenfd )//如果是服务端socket描述符,就接收客户端fd,并处理数据,加入定时器链表

{

struct sockaddr_in client_address;

socklen_t client_addrlength = sizeof( client_address );

int connfd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength );

addfd( epollfd, connfd );

users[connfd].address = client_address;

users[connfd].sockfd = connfd;

util_timer* timer = new util_timer;

timer->user_data = &users[connfd];

timer->cb_func = cb_func;

time_t cur = time( NULL );

timer->expire = cur + 3 * TIMESLOT;

users[connfd].timer = timer;

timer_lst.add_timer( timer );

}

else if( ( sockfd == pipefd[0] ) && ( events[i].events & EPOLLIN ) )

{//处理信号

int sig;

char signals[1024];

ret = recv( pipefd[0], signals, sizeof( signals ), 0 );

if( ret == -1 )

{

// handle the error

continue;

}

else if( ret == 0 )

{

continue;

}

else

{

for( int i = 0; i < ret; ++i )

{

switch( signals[i] )

{

case SIGALRM:

{

timeout = true;

break;

}

case SIGTERM:

{

stop_server = true;

}

}

}

}

}

else if( events[i].events & EPOLLIN )

{//处理客户端数据

memset( users[sockfd].buf, '\0', BUFFER_SIZE );

ret = recv( sockfd, users[sockfd].buf, BUFFER_SIZE-1, 0 );

printf( "get %d bytes of client data %s from %d\n", ret, users[sockfd].buf, sockfd );

util_timer* timer = users[sockfd].timer;

if( ret < 0 )

{

if( errno != EAGAIN )

{

cb_func( &users[sockfd] );

if( timer )

{

timer_lst.del_timer( timer );

}

}

}

else if( ret == 0 )

{

cb_func( &users[sockfd] );

if( timer )

{

timer_lst.del_timer( timer );

}

}

else

{

//send( sockfd, users[sockfd].buf, BUFFER_SIZE-1, 0 );

if( timer )

{

time_t cur = time( NULL );

timer->expire = cur + 3 * TIMESLOT;

printf( "adjust timer once\n" );

timer_lst.adjust_timer( timer );

}

}

}

else

{

// others

}

}

if( timeout )

{

timer_handler();

timeout = false;

}

}

close( listenfd );

close( pipefd[1] );

close( pipefd[0] );

delete [] users;

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值