一個windows下基於select多路分離器的Reactor模型

來源:互聯網
上載者:User

1.封裝了windows下同步變數,包括實現condition,monitor.本來想封裝線程,想著還要封裝類似boost::bind或者signal/solt的,放棄了.

2.該Reactor模型不排除在同一個socket上投遞多個eventhandler.一個eventhandler只針對一個socket事件處理(可讀,可寫.當然事件可以用掩碼,本例沒有採用這種做法.)

3.採用VS2005編譯.工程攜帶了一個測試server和一個只用於發送資料的client,一個同時收發的client

 

4.代碼摘錄:

 

Eventhandler

class sCEventhandler<br />{<br />public:<br />sCEventhandler(void);<br />virtual ~sCEventhandler(void);</p><p>virtual int Handler_Read(){return 1;}<br />virtual int Handler_Write(){return 1;}<br />virtual int Handler_Expet(){return 1;}<br />virtual void Handler_Closed(){delete this;}<br />};</p><p>enum HandlerType<br />{<br />HANDLE_CONNECT,<br />HANDLE_ACCEPT,<br />HANDLE_WRITE,<br />HANDLE_READ,<br />HANDLE_EXPT<br />};</p><p>class sCSocketHandler : public sCEventhandler<br />{<br />public:<br />sCSocketHandler(){};<br />sCSocketHandler(sCSocket s,HandlerType e);<br />void SetSocket(sCSocket s,HandlerType e){m_sk = s;m_e = e;}<br />sCSocket GetSocket();<br />HandlerType GetType();</p><p>protected:<br />sCSocket m_sk;<br />HandlerType m_e;<br />};

 

同步變數:

class MySyncObject<br />{<br />public:<br />MySyncObject(void);<br />virtual ~MySyncObject(void);<br />virtual BOOL lock(DWORD time = INFINITE);<br />virtual BOOL unlock() = 0;<br />virtual BOOL unlock(long count,long* preCount = NULL){return TRUE;}<br />operator HANDLE(){ return m_handle;}<br />protected:<br />HANDLE m_handle;<br />};</p><p>class MyMutex : public MySyncObject<br />{<br />public:<br />MyMutex( LPSECURITY_ATTRIBUTES lpas = NULL,BOOL bOwner = TRUE, LPCTSTR name = NULL)<br />{<br />m_handle = ::CreateMutex(lpas,bOwner,name);<br />}<br />BOOL unlock()<br />{<br />return ::ReleaseMutex(m_handle);<br />}</p><p>virtual ~MyMutex()<br />{<br />}<br />};</p><p>class MySemphore : public MySyncObject<br />{<br />public:<br />MySemphore( long lInital = 1,long lMax = 1,LPSECURITY_ATTRIBUTES lpas = NULL,LPCTSTR name = NULL)<br />{<br />m_handle = ::CreateSemaphore(lpas,lInital,lMax,name);<br />}<br />BOOL unlock()<br />{<br />return unlock(1);<br />}<br />BOOL unlock(long count,long* preCount = NULL)<br />{<br />return ::ReleaseSemaphore(m_handle,count,preCount);<br />}<br />};</p><p>class MyCondition<br />{<br />public:<br />MyCondition() : m_Semhpore(0,1),m_count(0){}<br />void wait( MyMutex& mutex,DWORD time = INFINITE);<br />void noticeOne();<br />void noticeAll();<br />private:<br />MySemphore m_Semhpore;<br />long m_count;<br />};</p><p>class MyMonitor : public MySyncObject<br />{<br />public:<br />MyMonitor():m_mutex(NULL,FALSE){}<br />BOOL lock(DWORD time = INFINITE );<br />BOOL unlock();<br />void wait(DWORD time = INFINITE);<br />void noticeOne();<br />void noticeAll();<br />private:<br />MyMutex m_mutex;<br />MyCondition m_condition;<br />};

 

Reactor主執行函數:

void sCReactor::Run()<br />{<br />//沒有listen或connect的阻塞在此<br />if ( m_FdRead.fd_count == 0 && m_FdWrite.fd_count==0 && m_FdExept.fd_count==0)<br />{<br />m_mutex.lock();<br />m_condition.wait(m_mutex);<br />m_mutex.unlock();<br />}<br />while(true)<br />{<br />fd_set fd_read,fd_write,fd_exept;<br />memcpy(&fd_read,&m_FdRead,sizeof(m_FdRead));<br />memcpy(&fd_write,&m_FdWrite,sizeof(m_FdWrite));<br />memcpy(&fd_exept,&m_FdExept,sizeof(m_FdExept));<br />int ret = select(0,&fd_read,&fd_write,&fd_exept,NULL);<br />if ( ret ==SOCKET_ERROR)<br />{</p><p>}<br />else if(ret > 0)<br />{<br />m_mutex.lock();<br />while( ret-->0)<br />{<br />//在一個socket上能同時發生可讀/可寫<br />// 注意: 一個socket上對應多個handler,可能導致不應該處理的handler調用了,而應該調用的handler沒有被調用.<br />//注意二:handler的處理函數中,如果有register或者removehandler的操作,導致iterator自增操作出現問題<br />for (std::set<sCSocketHandler*>::iterator it = m_handlers.begin();it!=m_handlers.end();++it)<br />{<br />sCSocketHandler* handler = *it;<br />int result = 0;<br />bool bProcess = false;<br />HandlerType e = handler->GetType();<br />if ( FD_ISSET(handler->GetSocket(),&fd_read))<br />{<br />if ( e == HANDLE_ACCEPT || e == HANDLE_READ)<br />{<br />result = handler->Handler_Read();<br />bProcess = true;<br />FD_CLR(handler->GetSocket(),&fd_read);<br />}<br />}<br />else if ( FD_ISSET(handler->GetSocket(),&fd_write))<br />{<br />if ( e == HANDLE_CONNECT || e == HANDLE_WRITE)<br />{<br />result = handler->Handler_Write();<br />bProcess = true;<br />FD_CLR(handler->GetSocket(),&fd_write);<br />}<br />}<br />else if( FD_ISSET(handler->GetSocket(),&fd_exept))<br />{<br />result = handler->Handler_Expet();<br />bProcess = true;<br />FD_CLR(handler->GetSocket(),&fd_exept);<br />}<br />if ( bProcess)<br />{<br />if ( result < 0)<br />{<br />if ( result == -2)<br />{<br />//-2定義為socket關閉,相關的handler都要清掉<br />sCSocket earseSocket = handler->GetSocket();<br />for ( std::set<sCSocketHandler*>::iterator it = m_handlers.begin();it!=m_handlers.end();)<br />{<br />sCSocketHandler* earseHandler = *it;<br />if ( earseHandler->GetSocket() == earseSocket)<br />{<br />RemoveHandler(earseHandler);<br />it = m_handlers.begin();<br />earseHandler->Handler_Closed();<br />}<br />else<br />{<br />++it;<br />}</p><p>}<br />}<br />else<br />{<br />RemoveHandler(handler);<br />}<br />}<br />break;<br />}<br />}<br />}<br />m_mutex.unlock();<br />}<br />}<br />}

 

測試服務端代碼:

void main(int argc,char** argv)<br />{<br />SocketGuard guard;<br />sCReactor reactor;<br />CServerAppector server(&reactor);<br />server.Open(sCSocketAddress("127.0.0.1",7000),&reactor);<br />while( true)<br />{<br />Sleep(100000);<br />}<br />}

 

完整工程例子下載連結:http://download.csdn.net/source/2938873

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.