Posted on 2009-02-01 11:15
dennis 閱讀(3370)
評(píng)論(0) 編輯 收藏 所屬分類:
java 、
linux & C
過(guò)去推薦過(guò)兩篇blog《Java NIO類庫(kù)Selector機(jī)制解析》(
上,
下),感嘆java為了跨平臺(tái)似乎“很傻很天真”。最近學(xué)習(xí)使用ACE,才知道這個(gè)解決辦法倒不是java開(kāi)創(chuàng)的,ACE也是這樣搞的。java nio中Selector的wakeup方法,類似于ACE_Select_Reactor的notify機(jī)制,可以從非select調(diào)用的線程去喚醒阻塞在select調(diào)用上的select線程,當(dāng)然ACE_Select_Reactor的notify強(qiáng)大多了,可以實(shí)現(xiàn)event handler的無(wú)限擴(kuò)容。ACE_Select_Reactor的notify的實(shí)現(xiàn)是通過(guò)ACE_Pipe,在ACE_Pipe中可以清晰地看到針對(duì)win32平臺(tái)是采用了TCP連接:
#if defined (ACE_LACKS_SOCKETPAIR) || defined (__Lynx__)
ACE_INET_Addr my_addr;
ACE_SOCK_Acceptor acceptor;
ACE_SOCK_Connector connector;
ACE_SOCK_Stream reader;
ACE_SOCK_Stream writer;
int result = 0;
# if defined (ACE_WIN32)
ACE_INET_Addr local_any (static_cast<u_short> (0), ACE_LOCALHOST);
# else
ACE_Addr local_any = ACE_Addr::sap_any;
# endif /* ACE_WIN32 */
// Bind listener to any port and then find out what the port was.
if (acceptor.open (local_any) == -1
|| acceptor.get_local_addr (my_addr) == -1)
result = -1;
else
{
ACE_INET_Addr sv_addr (my_addr.get_port_number (),
ACE_LOCALHOST);
// Establish a connection within the same process.
if (connector.connect (writer, sv_addr) == -1)
result = -1;
else if (acceptor.accept (reader) == -1)
{
writer.close ();
result = -1;
}
}
// Close down the acceptor endpoint since we don't need it anymore.
acceptor.close ();
在類unix平臺(tái)是采用STREAMS管道,在一些遺留的unix平臺(tái)上是socketpair()。為什么在win32上采用TCP連接的方式呢?原因不是什么性能、資源問(wèn)題,也不是因?yàn)閣indows管道消耗的資源比tcp多,而是由于winsock的select函數(shù)(java nio的select在win32下是使用select實(shí)現(xiàn)的)是無(wú)法監(jiān)測(cè)管道事件的,也就是說(shuō)無(wú)法將windows管道加入到fd_set中,為了做到可移植,才在win32上采用了TCP連接的方式來(lái)實(shí)現(xiàn)。這一點(diǎn)在blog上篇的新回復(fù)中已經(jīng)有人提到。