├── Makefile ├── README.md └── src ├── Makefile ├── client.cpp ├── epoll_demultiplexer.cpp ├── epoll_demultiplexer.h ├── event.h ├── event_demultiplexer.h ├── event_handle.h ├── listen_handle.cpp ├── listen_handle.h ├── reactor.cpp ├── reactor.h ├── reactor_impl.cpp ├── reactor_impl.h ├── select_demultiplexer.cpp ├── select_demultiplexer.h ├── server.cpp ├── sock_handle.cpp └── sock_handle.h /Makefile: -------------------------------------------------------------------------------- 1 | epoll: 2 | cd src; $(MAKE) "PLAT=-D_USE_EPOLL" "DEMULTIPLEX=epoll_demultiplexer.o" 3 | 4 | select: 5 | cd src; $(MAKE) "PLAT=-D_USE_SELECT" "DEMULTIPLEX=select_demultiplexer.o" 6 | 7 | clean: 8 | cd src; $(MAKE) clean 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | reactor 2 | ======= 3 | 一个简单的reactor模式的实现。目前只支持select和epoll两种多路复用的实现。 4 | 如果要使用select,则可使用编译参数 5 | make select 6 | 如果要实现epoll,则使用编译参数 7 | make epoll 8 | 9 | 代码中用这个reactor实现了一个反射服务器。 10 | 由于项目是练手项目,在socket异常处理部分做得比较简单,有兴趣得同学自行完善下 11 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | CFLAGS=-g -Wall 3 | PLAT=-DEPOLL 4 | DEMULTIPLEX=epoll_demultiplexer.o 5 | OBJS=$(DEMULTIPLEX) reactor.o reactor_impl.o listen_handle.o sock_handle.o 6 | BIN=client server 7 | 8 | .SUFFIXES:.cpp .o 9 | 10 | .cpp.o: 11 | $(CXX) -c $< $(CFLAGS) $(PLAT) 12 | 13 | all:$(BIN) 14 | 15 | server:server.o $(OBJS) 16 | $(CXX) $^ -o $@ 17 | 18 | client:client.o 19 | $(CXX) $^ -o $@ 20 | 21 | clean: 22 | $(RM) *.o $(BIN) core* 23 | -------------------------------------------------------------------------------- /src/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int main( int argc, char **argv ) 12 | { 13 | int sockfd = -1; 14 | 15 | if ( 0 > ( sockfd = socket( AF_INET, SOCK_STREAM, 0) ) ) 16 | { 17 | printf("socket error:%s\n", strerror(errno) ); 18 | exit(-1); 19 | } 20 | 21 | struct sockaddr_in seraddr; 22 | seraddr.sin_family = AF_INET; 23 | seraddr.sin_port = htons( 9876 ); 24 | seraddr.sin_addr.s_addr = inet_addr( "127.0.0.1" ); 25 | if ( 0 > connect( sockfd, (struct sockaddr*)&seraddr, sizeof(seraddr) ) ) 26 | { 27 | printf("connect error:%s\n", strerror(errno) ); 28 | exit(-2); 29 | }else{ 30 | printf("connect ok\n"); 31 | } 32 | 33 | char wbuf[64] = {0}; 34 | strcpy( wbuf, "hello world"); 35 | int n = write( sockfd, wbuf, strlen(wbuf) ); 36 | 37 | char rbuf[64] = {0}; 38 | memset( rbuf, 0, sizeof(rbuf) ); 39 | n = read( sockfd, rbuf, sizeof(rbuf) ); 40 | printf("send [ %s ]; reply [ %s ] \n", wbuf, rbuf ); 41 | 42 | if ( n < 0 ) 43 | { 44 | printf("read error:%s\n", strerror(errno) ); 45 | exit(-3); 46 | } 47 | 48 | close(sockfd); 49 | 50 | return 0; 51 | } 52 | 53 | -------------------------------------------------------------------------------- /src/epoll_demultiplexer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "stdio.h" 9 | 10 | #include "event.h" 11 | #include "event_handle.h" 12 | #include "event_demultiplexer.h" 13 | #include "epoll_demultiplexer.h" 14 | 15 | const int EpollDemultiplexer::max_event = 1024; 16 | EpollDemultiplexer::EpollDemultiplexer() 17 | :epoll_fd(-1) 18 | { 19 | epoll_fd = epoll_create( max_event ); 20 | evs.resize( max_event ); 21 | } 22 | 23 | EpollDemultiplexer::~EpollDemultiplexer() 24 | { 25 | if( epoll_fd != -1 ) 26 | close( epoll_fd ); 27 | } 28 | 29 | int EpollDemultiplexer::wait_event( std::map& handlers, 30 | int timeout ) 31 | { 32 | 33 | int num = epoll_wait( epoll_fd, &evs[0], max_event, timeout ); 34 | 35 | for ( int i = 0; i < num; ++i ) 36 | { 37 | EventHandler* handler = (EventHandler*)evs[i].data.ptr; 38 | 39 | if ( (EPOLLIN) & evs[i].events ) 40 | { 41 | handler->handle_read(); 42 | } 43 | 44 | if ( EPOLLOUT & evs[i].events ) 45 | { 46 | handler->handle_write(); 47 | } 48 | if ( (EPOLLRDHUP | EPOLLHUP | EPOLLERR) & evs[i].events ) 49 | { 50 | handler->handle_error(); 51 | } 52 | } 53 | 54 | return num; 55 | } 56 | 57 | int EpollDemultiplexer::regist(EventHandler* handler, Event evt) 58 | { 59 | struct epoll_event ev; 60 | 61 | ev.data.ptr = (void*)handler; 62 | 63 | if ( evt & ReadEvent ) 64 | { 65 | ev.events |= EPOLLIN; 66 | ev.events |= EPOLLET; 67 | } 68 | if ( evt & WriteEvent ) 69 | { 70 | ev.events |= EPOLLOUT; 71 | } 72 | 73 | if ( 0 != epoll_ctl( epoll_fd, EPOLL_CTL_ADD, handler->get_handle(), &ev ) ) 74 | { 75 | if ( errno == ENOENT ) 76 | { 77 | if ( 0 != epoll_ctl( epoll_fd, EPOLL_CTL_ADD, handler->get_handle(), &ev ) ) 78 | { 79 | printf("epoll_ctrl add error : %s\n", strerror(errno)); 80 | return -errno; 81 | } 82 | } 83 | } 84 | 85 | return 0; 86 | } 87 | 88 | int EpollDemultiplexer::remove(Handle handle) 89 | { 90 | struct epoll_event ev; 91 | 92 | if ( 0 != epoll_ctl( epoll_fd, EPOLL_CTL_DEL, handle, &ev ) ) 93 | { 94 | printf("epoll_ctrl del error : %s\n", strerror(errno)); 95 | return -errno; 96 | } 97 | 98 | return 0; 99 | } 100 | 101 | -------------------------------------------------------------------------------- /src/epoll_demultiplexer.h: -------------------------------------------------------------------------------- 1 | #ifndef _REACTOR_EPOLL_H_ 2 | #define _REACTOR_EPOLL_H_ 3 | 4 | #include 5 | #include 6 | 7 | class EpollDemultiplexer : public EventDemultiplexer 8 | { 9 | public: 10 | EpollDemultiplexer(); 11 | virtual ~EpollDemultiplexer(); 12 | 13 | virtual int wait_event( std::map& handlers, 14 | int timeout = 0) ; 15 | virtual int regist(EventHandler* handle, Event evt) ; 16 | virtual int remove(Handle handle) ; 17 | 18 | private: 19 | static const int max_event; 20 | int epoll_fd; 21 | std::vector evs; 22 | }; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/event.h: -------------------------------------------------------------------------------- 1 | #ifndef _REACTOR_EVENT_H_ 2 | #define _REACTOR_EVENT_H_ 3 | 4 | typedef unsigned int Event; 5 | enum EventMask 6 | { 7 | ReadEvent = 0x01, 8 | WriteEvent = 0x02, 9 | ErrorEvent = 0x04, 10 | EventMask = 0xff 11 | }; 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/event_demultiplexer.h: -------------------------------------------------------------------------------- 1 | #ifndef _REACTOR_EVENTDEMULTIPLEXER_H_ 2 | #define _REACTOR_EVENTDEMULTIPLEXER_H_ 3 | 4 | class EventDemultiplexer 5 | { 6 | public: 7 | EventDemultiplexer() {} 8 | virtual ~EventDemultiplexer() {} 9 | virtual int wait_event( std::map& handlers, 10 | int timeout = 0) = 0; 11 | virtual int regist(EventHandler* handle, Event evt) = 0; 12 | virtual int remove(Handle handle) = 0; 13 | }; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/event_handle.h: -------------------------------------------------------------------------------- 1 | #ifndef _REACTOR_HANDLE_H_ 2 | #define _REACTOR_HANDLE_H_ 3 | 4 | 5 | typedef int Handle; 6 | 7 | class EventHandler 8 | { 9 | public: 10 | EventHandler() {} 11 | virtual ~EventHandler() {} 12 | virtual Handle get_handle() const = 0; 13 | virtual void handle_read() = 0; 14 | virtual void handle_write() = 0; 15 | virtual void handle_error() = 0; 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/listen_handle.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "stdio.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | #include 15 | 16 | #include "event_handle.h" 17 | #include "sock_handle.h" 18 | #include "reactor.h" 19 | #include "listen_handle.h" 20 | 21 | ListenHandle::ListenHandle( ) 22 | :listenfd(-1) 23 | { 24 | 25 | } 26 | 27 | ListenHandle::~ListenHandle() 28 | { 29 | if ( listenfd != -1 ) 30 | close( listenfd ); 31 | } 32 | 33 | void ListenHandle::handle_read() 34 | { 35 | int fd = accept( listenfd, NULL, NULL ); 36 | printf("new connect\n"); 37 | 38 | SockHandle *h = new SockHandle( fd ); 39 | setNonBlocking(h->get_handle()); 40 | 41 | Reactor& r = Reactor::get_instance(); 42 | r.regist( h, ReadEvent ); 43 | } 44 | 45 | void ListenHandle::handle_error() 46 | { 47 | 48 | } 49 | 50 | bool ListenHandle::listenOn( int port ){ 51 | if( 0 > (listenfd = socket( AF_INET, SOCK_STREAM, 0 ) ) ) 52 | { 53 | printf("socket error:%s\n", strerror(errno) ); 54 | return false; 55 | } 56 | 57 | struct sockaddr_in seraddr; 58 | seraddr.sin_family = AF_INET; 59 | seraddr.sin_port = htons( port ); 60 | seraddr.sin_addr.s_addr = htonl( INADDR_ANY ); 61 | 62 | if ( 0 > bind( listenfd, (struct sockaddr*)&seraddr, sizeof(seraddr) ) ) 63 | { 64 | printf("bind error:%s\n", strerror(errno) ); 65 | return false; 66 | } 67 | 68 | int sockoptval = 1; 69 | if ( 0 > setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &sockoptval, sizeof(sockoptval)) ){ 70 | printf("setsockopt error:%s\n", strerror( errno ) ); 71 | return false; 72 | } 73 | 74 | setNonBlocking( listenfd ); 75 | 76 | if ( 0 > listen( listenfd, 5 ) ) 77 | { 78 | printf("listen error:%s\n", strerror( errno ) ); 79 | return false; 80 | } 81 | 82 | 83 | return true; 84 | } 85 | 86 | 87 | void ListenHandle::setNonBlocking( int fd){ 88 | int option = fcntl( fd, F_GETFL ); 89 | option |= O_NONBLOCK; 90 | fcntl( fd, option ); 91 | } 92 | -------------------------------------------------------------------------------- /src/listen_handle.h: -------------------------------------------------------------------------------- 1 | #ifndef _REACTOR_LISTEN_HANDLE_H_ 2 | #define _REACTOR_LISTEN_HANDLE_H_ 3 | 4 | class ListenHandle : public EventHandler 5 | { 6 | public: 7 | ListenHandle(); 8 | virtual ~ListenHandle(); 9 | 10 | virtual Handle get_handle() const { return listenfd; } 11 | virtual void handle_read(); 12 | virtual void handle_write() {} 13 | virtual void handle_error(); 14 | 15 | bool listenOn( int port ); 16 | 17 | private: 18 | void setNonBlocking( int fd ); 19 | 20 | private: 21 | Handle listenfd; 22 | }; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/reactor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include "reactor.h" 7 | 8 | Reactor Reactor::reactor; 9 | 10 | Reactor& Reactor::get_instance() 11 | { 12 | return reactor; 13 | } 14 | 15 | Reactor::Reactor() 16 | { 17 | impl = new ReactorImplementation(); 18 | } 19 | 20 | Reactor::~Reactor() 21 | { 22 | if ( impl ) 23 | delete impl; 24 | } 25 | 26 | int Reactor::regist( EventHandler* handle, Event evt ) 27 | { 28 | return impl->regist( handle, evt ); 29 | } 30 | 31 | void Reactor::remove( EventHandler* handle ) 32 | { 33 | return impl->remove( handle ); 34 | } 35 | 36 | void Reactor::event_loop( int timeout ) 37 | { 38 | impl->event_loop( timeout ); 39 | } 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/reactor.h: -------------------------------------------------------------------------------- 1 | #ifndef REACTOR_REACTOR_H_ 2 | #define REACTOR_REACTOR_H_ 3 | 4 | #include "event.h" 5 | #include "event_handle.h" 6 | #include "event_demultiplexer.h" 7 | #include "reactor_impl.h" 8 | 9 | class ReactorImplementation; 10 | 11 | class Reactor 12 | { 13 | public: 14 | static Reactor& get_instance(); 15 | 16 | int regist(EventHandler * handler, Event evt); 17 | void remove(EventHandler * handler); 18 | void event_loop(int timeout = 0); 19 | 20 | private: 21 | Reactor(); 22 | ~Reactor(); 23 | Reactor(const Reactor &); 24 | Reactor & operator=(const Reactor &); 25 | 26 | private: 27 | ReactorImplementation* impl; 28 | static Reactor reactor; 29 | }; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/reactor_impl.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "event.h" 4 | #include "event_handle.h" 5 | #include "event_demultiplexer.h" 6 | 7 | #ifdef _USE_EPOLL 8 | #include "epoll_demultiplexer.h" 9 | #endif 10 | #ifdef _USE_SELECT 11 | #include 12 | #include 13 | #include "select_demultiplexer.h" 14 | #endif 15 | 16 | #include "reactor_impl.h" 17 | 18 | ReactorImplementation::ReactorImplementation() 19 | { 20 | #ifdef _USE_EPOLL 21 | demultiplexer = new EpollDemultiplexer(); 22 | #endif 23 | #ifdef _USE_SELECT 24 | demultiplexer = new SelectDemultiplexer(); 25 | #endif 26 | } 27 | 28 | ReactorImplementation::~ReactorImplementation() 29 | { 30 | if ( demultiplexer ) 31 | delete demultiplexer; 32 | } 33 | 34 | int ReactorImplementation::regist( EventHandler* handler, Event evt ) 35 | { 36 | return demultiplexer->regist( handler, evt ); 37 | } 38 | 39 | void ReactorImplementation::remove( EventHandler* handler ) 40 | { 41 | int handle = handler->get_handle(); 42 | demultiplexer->remove( handle ); 43 | } 44 | 45 | void ReactorImplementation::event_loop( int timeout ) 46 | { 47 | demultiplexer->wait_event( handlers, timeout ); 48 | } 49 | 50 | -------------------------------------------------------------------------------- /src/reactor_impl.h: -------------------------------------------------------------------------------- 1 | #ifndef _REACTOR_IMPL_H_ 2 | #define _REACTPR_IMPL_H_ 3 | 4 | class ReactorImplementation 5 | { 6 | public: 7 | ReactorImplementation(); 8 | ~ReactorImplementation(); 9 | 10 | typedef std::map::iterator iterator; 11 | 12 | int regist(EventHandler* handler, Event evt); 13 | void remove(EventHandler* handler); 14 | void event_loop(int timeout = 0 ); 15 | 16 | private: 17 | EventDemultiplexer* demultiplexer; 18 | std::map handlers; 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/select_demultiplexer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "event.h" 14 | #include "event_handle.h" 15 | #include "event_demultiplexer.h" 16 | #include "select_demultiplexer.h" 17 | 18 | SelectDemultiplexer::SelectDemultiplexer() 19 | { 20 | FD_ZERO( &read_set ); 21 | FD_ZERO( &write_set ); 22 | FD_ZERO( &err_set ); 23 | } 24 | 25 | SelectDemultiplexer::~SelectDemultiplexer() 26 | { 27 | 28 | } 29 | 30 | int SelectDemultiplexer::regist( Handle handle, Event evt ) 31 | { 32 | if ( evt | ReadEvent ) 33 | FD_SET( handle, &read_set ); 34 | if ( evt | WriteEvent ) 35 | FD_SET ( handle, &write_set ); 36 | 37 | FD_SET ( handle, &err_set ); 38 | 39 | return 0; 40 | } 41 | 42 | int SelectDemultiplexer::remove(Handle handle) 43 | { 44 | FD_CLR( handle, &read_set ); 45 | FD_CLR( handle, &write_set ); 46 | FD_CLR( handle, &err_set ); 47 | 48 | return 0; 49 | } 50 | 51 | int SelectDemultiplexer::wait_event( std::map& handlers, int timeout ) 52 | { 53 | struct timeval* ptv; 54 | 55 | struct timeval tv; 56 | 57 | if ( timeout > 0 ) 58 | { 59 | tv.tv_sec = timeout / 1000; 60 | tv.tv_usec = timeout % 1000 * 1000; 61 | ptv = &tv; 62 | } 63 | else 64 | ptv = NULL; 65 | 66 | 67 | int max_fd = handlers.rbegin()->first + 1; 68 | int num = select( max_fd, &read_set, &write_set, &err_set, ptv ); 69 | 70 | if ( num < 0 ) 71 | { 72 | printf("select error %s\n", strerror(errno) ); 73 | return -1; 74 | } 75 | else if ( num == 0 ) 76 | return num; 77 | 78 | std::map::iterator it = handlers.begin(); 79 | while ( it != handlers.end() ) 80 | { 81 | /* 82 | if ( FD_ISSET( it->first, &err_set ) ) 83 | { 84 | printf("%d error event\n", it->first); 85 | handlers[ it->first ]->handle_error(); 86 | FD_CLR( it->first, &read_set ); 87 | FD_CLR( it->first, &write_set ); 88 | } 89 | else 90 | */ 91 | { 92 | if ( FD_ISSET( it->first, &read_set ) ) 93 | { 94 | printf("%d read event\n",it->first); 95 | handlers[ it->first ]->handle_read(); 96 | FD_CLR( it->first, &write_set ); 97 | FD_CLR( it->first, &err_set ); 98 | } 99 | if ( FD_ISSET( it->first, &write_set ) ) 100 | { 101 | printf("%d write event\n", it->first); 102 | handlers[ it->first ]->handle_write(); 103 | FD_CLR( it->first, &err_set ); 104 | FD_CLR( it->first, &read_set ); 105 | } 106 | ++it; 107 | } 108 | } 109 | 110 | return num; 111 | } 112 | 113 | -------------------------------------------------------------------------------- /src/select_demultiplexer.h: -------------------------------------------------------------------------------- 1 | #ifndef _REACTOR_SELECT_H_ 2 | #define _REACTOR_SELECT_H_ 3 | 4 | class SelectDemultiplexer : public EventDemultiplexer 5 | { 6 | public: 7 | SelectDemultiplexer(); 8 | virtual ~SelectDemultiplexer(); 9 | 10 | virtual int wait_event( std::map& handlers, 11 | int timeout = 0) ; 12 | virtual int regist(Handle handle, Event evt) ; 13 | virtual int remove(Handle handle) ; 14 | 15 | private: 16 | fd_set read_set; 17 | fd_set write_set; 18 | fd_set err_set; 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include "event_handle.h" 13 | #include "reactor.h" 14 | #include "listen_handle.h" 15 | #include "sock_handle.h" 16 | 17 | int main(int argc, char **argv) 18 | { 19 | ListenHandle* handle = new ListenHandle( ); 20 | handle->listenOn(9876); 21 | Reactor& actor = Reactor::get_instance(); 22 | actor.regist( handle, ReadEvent ); 23 | 24 | while( true ) 25 | { 26 | actor.event_loop( -1 ); 27 | printf("one loop\n"); 28 | } 29 | 30 | return 0; 31 | } 32 | 33 | -------------------------------------------------------------------------------- /src/sock_handle.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include "event_handle.h" 8 | #include "reactor.h" 9 | #include "sock_handle.h" 10 | 11 | SockHandle::SockHandle( Handle fd ) 12 | :sock_fd(fd), buf( new char[MAX_SIZE] ) 13 | { 14 | memset( buf, 0, MAX_SIZE ); 15 | } 16 | 17 | SockHandle::~SockHandle() 18 | { 19 | close( sock_fd ); 20 | delete[] buf; 21 | } 22 | 23 | Handle SockHandle::get_handle() const 24 | { 25 | return sock_fd; 26 | } 27 | 28 | void SockHandle::handle_read() 29 | { 30 | printf("on read\n"); 31 | if ( 0 < read( sock_fd, buf, MAX_SIZE ) ) 32 | { 33 | write( sock_fd, buf, strlen(buf) ); 34 | }else{ 35 | handle_error(); 36 | } 37 | } 38 | 39 | void SockHandle::handle_write() 40 | { 41 | 42 | } 43 | 44 | void SockHandle::handle_error() 45 | { 46 | Reactor& r = Reactor::get_instance(); 47 | r.remove( this ); 48 | delete this; 49 | } 50 | 51 | -------------------------------------------------------------------------------- /src/sock_handle.h: -------------------------------------------------------------------------------- 1 | #ifndef _REACTOR_SOCK_HANDLE_H_ 2 | #define _REACTOR_SOCK_HANDLE_H_ 3 | 4 | class SockHandle : public EventHandler 5 | { 6 | public: 7 | SockHandle( Handle fd ); 8 | virtual ~SockHandle(); 9 | 10 | virtual Handle get_handle() const; 11 | virtual void handle_read(); 12 | virtual void handle_write(); 13 | virtual void handle_error(); 14 | 15 | private: 16 | Handle sock_fd; 17 | char* buf; 18 | static const int MAX_SIZE = 1024; 19 | }; 20 | 21 | #endif 22 | --------------------------------------------------------------------------------