mirror of
https://github.com/pocoproject/poco.git
synced 2025-04-15 22:50:36 +02:00
Socket::select and SocketReactor improvements
This commit is contained in:
parent
9b636a3fbd
commit
8e58146848
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// Socket.h
|
// Socket.h
|
||||||
//
|
//
|
||||||
// $Id: //poco/svn/Net/include/Poco/Net/Socket.h#3 $
|
// $Id: //poco/1.3/Net/include/Poco/Net/Socket.h#3 $
|
||||||
//
|
//
|
||||||
// Library: Net
|
// Library: Net
|
||||||
// Package: Sockets
|
// Package: Sockets
|
||||||
@ -129,6 +129,10 @@ public:
|
|||||||
/// * readList contains those sockets ready for reading,
|
/// * readList contains those sockets ready for reading,
|
||||||
/// * writeList contains those sockets ready for writing,
|
/// * writeList contains those sockets ready for writing,
|
||||||
/// * exceptList contains those sockets with a pending error.
|
/// * exceptList contains those sockets with a pending error.
|
||||||
|
///
|
||||||
|
/// If the total number of sockets passed in readList, writeList and
|
||||||
|
/// exceptList is zero, select() will return immediately and the
|
||||||
|
/// return value will be 0.
|
||||||
|
|
||||||
bool poll(const Poco::Timespan& timeout, int mode) const;
|
bool poll(const Poco::Timespan& timeout, int mode) const;
|
||||||
/// Determines the status of the socket, using a
|
/// Determines the status of the socket, using a
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// SocketNotification.h
|
// SocketNotification.h
|
||||||
//
|
//
|
||||||
// $Id: //poco/svn/Net/include/Poco/Net/SocketNotification.h#2 $
|
// $Id: //poco/1.3/Net/include/Poco/Net/SocketNotification.h#2 $
|
||||||
//
|
//
|
||||||
// Library: Net
|
// Library: Net
|
||||||
// Package: Reactor
|
// Package: Reactor
|
||||||
@ -128,6 +128,19 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Net_API IdleNotification: public SocketNotification
|
||||||
|
/// This notification is sent when the SocketReactor does
|
||||||
|
/// not have any sockets to react to.
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IdleNotification(SocketReactor* pReactor);
|
||||||
|
/// Creates the IdleNotification for the given SocketReactor.
|
||||||
|
|
||||||
|
~IdleNotification();
|
||||||
|
/// Destroys the IdleNotification.
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Net_API ShutdownNotification: public SocketNotification
|
class Net_API ShutdownNotification: public SocketNotification
|
||||||
/// This notification is sent when the SocketReactor is
|
/// This notification is sent when the SocketReactor is
|
||||||
/// about to shut down.
|
/// about to shut down.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// SocketReactor.h
|
// SocketReactor.h
|
||||||
//
|
//
|
||||||
// $Id: //poco/svn/Net/include/Poco/Net/SocketReactor.h#2 $
|
// $Id: //poco/1.3/Net/include/Poco/Net/SocketReactor.h#2 $
|
||||||
//
|
//
|
||||||
// Library: Net
|
// Library: Net
|
||||||
// Package: Reactor
|
// Package: Reactor
|
||||||
@ -90,7 +90,8 @@ class Net_API SocketReactor: public Poco::Runnable
|
|||||||
/// If an event is detected, the corresponding event handler
|
/// If an event is detected, the corresponding event handler
|
||||||
/// is invoked. There are five event types (and corresponding
|
/// is invoked. There are five event types (and corresponding
|
||||||
/// notification classes) defined: ReadableNotification, WritableNotification,
|
/// notification classes) defined: ReadableNotification, WritableNotification,
|
||||||
/// ErrorNotification, TimeoutNotification and ShutdownNotification.
|
/// ErrorNotification, TimeoutNotification, IdleNotification and
|
||||||
|
/// ShutdownNotification.
|
||||||
///
|
///
|
||||||
/// The ReadableNotification will be dispatched if a socket becomes
|
/// The ReadableNotification will be dispatched if a socket becomes
|
||||||
/// readable. The WritableNotification will be dispatched if a socket
|
/// readable. The WritableNotification will be dispatched if a socket
|
||||||
@ -100,9 +101,17 @@ class Net_API SocketReactor: public Poco::Runnable
|
|||||||
/// If the timeout expires and no event has occured, a
|
/// If the timeout expires and no event has occured, a
|
||||||
/// TimeoutNotification will be dispatched to all event handlers
|
/// TimeoutNotification will be dispatched to all event handlers
|
||||||
/// registered for it. This is done in the onTimeout() method
|
/// registered for it. This is done in the onTimeout() method
|
||||||
/// which can be overridded by subclasses to perform custom
|
/// which can be overridden by subclasses to perform custom
|
||||||
/// timeout processing.
|
/// timeout processing.
|
||||||
///
|
///
|
||||||
|
/// If there are no sockets for the SocketReactor to pass to
|
||||||
|
/// Socket::select(), an IdleNotification will be dispatched to
|
||||||
|
/// all event handlers registered for it. This is done in the
|
||||||
|
/// onIdle() method which can be overridden by subclasses
|
||||||
|
/// to perform custom idle processing. Since onIdle() will be
|
||||||
|
/// called repeatedly in a loop, it is recommended to do a
|
||||||
|
/// short sleep or yield in the event handler.
|
||||||
|
///
|
||||||
/// Finally, when the SocketReactor is about to shut down (as a result
|
/// Finally, when the SocketReactor is about to shut down (as a result
|
||||||
/// of stop() being called), it dispatches a ShutdownNotification
|
/// of stop() being called), it dispatches a ShutdownNotification
|
||||||
/// to all event handlers. This is done in the onShutdown() method
|
/// to all event handlers. This is done in the onShutdown() method
|
||||||
@ -174,6 +183,13 @@ protected:
|
|||||||
/// Can be overridden by subclasses. The default implementation
|
/// Can be overridden by subclasses. The default implementation
|
||||||
/// dispatches the TimeoutNotification and thus should be called by overriding
|
/// dispatches the TimeoutNotification and thus should be called by overriding
|
||||||
/// implementations.
|
/// implementations.
|
||||||
|
|
||||||
|
virtual void onIdle();
|
||||||
|
/// Called if no sockets are available to call select() on.
|
||||||
|
///
|
||||||
|
/// Can be overridden by subclasses. The default implementation
|
||||||
|
/// dispatches the IdleNotification and thus should be called by overriding
|
||||||
|
/// implementations.
|
||||||
|
|
||||||
virtual void onShutdown();
|
virtual void onShutdown();
|
||||||
/// Called when the SocketReactor is about to terminate.
|
/// Called when the SocketReactor is about to terminate.
|
||||||
@ -208,6 +224,7 @@ private:
|
|||||||
NotificationPtr _pWritableNotification;
|
NotificationPtr _pWritableNotification;
|
||||||
NotificationPtr _pErrorNotification;
|
NotificationPtr _pErrorNotification;
|
||||||
NotificationPtr _pTimeoutNotification;
|
NotificationPtr _pTimeoutNotification;
|
||||||
|
NotificationPtr _pIdleNotification;
|
||||||
NotificationPtr _pShutdownNotification;
|
NotificationPtr _pShutdownNotification;
|
||||||
Poco::FastMutex _mutex;
|
Poco::FastMutex _mutex;
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// Socket.cpp
|
// Socket.cpp
|
||||||
//
|
//
|
||||||
// $Id: //poco/svn/Net/src/Socket.cpp#2 $
|
// $Id: //poco/1.3/Net/src/Socket.cpp#4 $
|
||||||
//
|
//
|
||||||
// Library: Net
|
// Library: Net
|
||||||
// Package: Sockets
|
// Package: Sockets
|
||||||
@ -112,6 +112,7 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce
|
|||||||
nfd = int(it->sockfd());
|
nfd = int(it->sockfd());
|
||||||
FD_SET(it->sockfd(), &fdExcept);
|
FD_SET(it->sockfd(), &fdExcept);
|
||||||
}
|
}
|
||||||
|
if (nfd == 0) return 0;
|
||||||
Poco::Timespan remainingTime(timeout);
|
Poco::Timespan remainingTime(timeout);
|
||||||
int rc;
|
int rc;
|
||||||
do
|
do
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// SocketNotification.cpp
|
// SocketNotification.cpp
|
||||||
//
|
//
|
||||||
// $Id: //poco/svn/Net/src/SocketNotification.cpp#2 $
|
// $Id: //poco/1.3/Net/src/SocketNotification.cpp#2 $
|
||||||
//
|
//
|
||||||
// Library: Net
|
// Library: Net
|
||||||
// Package: Reactor
|
// Package: Reactor
|
||||||
@ -102,6 +102,17 @@ TimeoutNotification::~TimeoutNotification()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IdleNotification::IdleNotification(SocketReactor* pReactor):
|
||||||
|
SocketNotification(pReactor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IdleNotification::~IdleNotification()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ShutdownNotification::ShutdownNotification(SocketReactor* pReactor):
|
ShutdownNotification::ShutdownNotification(SocketReactor* pReactor):
|
||||||
SocketNotification(pReactor)
|
SocketNotification(pReactor)
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// SocketReactor.cpp
|
// SocketReactor.cpp
|
||||||
//
|
//
|
||||||
// $Id: //poco/svn/Net/src/SocketReactor.cpp#2 $
|
// $Id: //poco/1.3/Net/src/SocketReactor.cpp#2 $
|
||||||
//
|
//
|
||||||
// Library: Net
|
// Library: Net
|
||||||
// Package: Reactor
|
// Package: Reactor
|
||||||
@ -38,6 +38,7 @@
|
|||||||
#include "Poco/Net/SocketNotification.h"
|
#include "Poco/Net/SocketNotification.h"
|
||||||
#include "Poco/Net/SocketNotifier.h"
|
#include "Poco/Net/SocketNotifier.h"
|
||||||
#include "Poco/ErrorHandler.h"
|
#include "Poco/ErrorHandler.h"
|
||||||
|
#include "Poco/Thread.h"
|
||||||
#include "Poco/Exception.h"
|
#include "Poco/Exception.h"
|
||||||
|
|
||||||
|
|
||||||
@ -57,6 +58,7 @@ SocketReactor::SocketReactor():
|
|||||||
_pWritableNotification(new WritableNotification(this)),
|
_pWritableNotification(new WritableNotification(this)),
|
||||||
_pErrorNotification(new ErrorNotification(this)),
|
_pErrorNotification(new ErrorNotification(this)),
|
||||||
_pTimeoutNotification(new TimeoutNotification(this)),
|
_pTimeoutNotification(new TimeoutNotification(this)),
|
||||||
|
_pIdleNotification(new IdleNotification(this)),
|
||||||
_pShutdownNotification(new ShutdownNotification(this))
|
_pShutdownNotification(new ShutdownNotification(this))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -69,6 +71,7 @@ SocketReactor::SocketReactor(const Poco::Timespan& timeout):
|
|||||||
_pWritableNotification(new WritableNotification(this)),
|
_pWritableNotification(new WritableNotification(this)),
|
||||||
_pErrorNotification(new ErrorNotification(this)),
|
_pErrorNotification(new ErrorNotification(this)),
|
||||||
_pTimeoutNotification(new TimeoutNotification(this)),
|
_pTimeoutNotification(new TimeoutNotification(this)),
|
||||||
|
_pIdleNotification(new IdleNotification(this)),
|
||||||
_pShutdownNotification(new ShutdownNotification(this))
|
_pShutdownNotification(new ShutdownNotification(this))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -87,31 +90,60 @@ void SocketReactor::run()
|
|||||||
|
|
||||||
while (!_stop)
|
while (!_stop)
|
||||||
{
|
{
|
||||||
readable.clear();
|
try
|
||||||
writable.clear();
|
|
||||||
except.clear();
|
|
||||||
{
|
{
|
||||||
FastMutex::ScopedLock lock(_mutex);
|
readable.clear();
|
||||||
for (EventHandlerMap::iterator it = _handlers.begin(); it != _handlers.end(); ++it)
|
writable.clear();
|
||||||
|
except.clear();
|
||||||
|
int nSockets = 0;
|
||||||
{
|
{
|
||||||
if (it->second->accepts(_pReadableNotification))
|
FastMutex::ScopedLock lock(_mutex);
|
||||||
readable.push_back(it->first);
|
for (EventHandlerMap::iterator it = _handlers.begin(); it != _handlers.end(); ++it)
|
||||||
if (it->second->accepts(_pWritableNotification))
|
{
|
||||||
writable.push_back(it->first);
|
if (it->second->accepts(_pReadableNotification))
|
||||||
if (it->second->accepts(_pErrorNotification))
|
{
|
||||||
except.push_back(it->first);
|
readable.push_back(it->first);
|
||||||
|
nSockets++;
|
||||||
|
}
|
||||||
|
if (it->second->accepts(_pWritableNotification))
|
||||||
|
{
|
||||||
|
writable.push_back(it->first);
|
||||||
|
nSockets++;
|
||||||
|
}
|
||||||
|
if (it->second->accepts(_pErrorNotification))
|
||||||
|
{
|
||||||
|
except.push_back(it->first);
|
||||||
|
nSockets++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (nSockets == 0)
|
||||||
|
{
|
||||||
|
onIdle();
|
||||||
|
}
|
||||||
|
else if (Socket::select(readable, writable, except, _timeout))
|
||||||
|
{
|
||||||
|
for (Socket::SocketList::iterator it = readable.begin(); it != readable.end(); ++it)
|
||||||
|
dispatch(*it, _pReadableNotification);
|
||||||
|
for (Socket::SocketList::iterator it = writable.begin(); it != writable.end(); ++it)
|
||||||
|
dispatch(*it, _pWritableNotification);
|
||||||
|
for (Socket::SocketList::iterator it = except.begin(); it != except.end(); ++it)
|
||||||
|
dispatch(*it, _pErrorNotification);
|
||||||
|
}
|
||||||
|
else onTimeout();
|
||||||
}
|
}
|
||||||
if (Socket::select(readable, writable, except, _timeout))
|
catch (Exception& exc)
|
||||||
{
|
{
|
||||||
for (Socket::SocketList::iterator it = readable.begin(); it != readable.end(); ++it)
|
ErrorHandler::handle(exc);
|
||||||
dispatch(*it, _pReadableNotification);
|
}
|
||||||
for (Socket::SocketList::iterator it = writable.begin(); it != writable.end(); ++it)
|
catch (std::exception& exc)
|
||||||
dispatch(*it, _pWritableNotification);
|
{
|
||||||
for (Socket::SocketList::iterator it = except.begin(); it != except.end(); ++it)
|
ErrorHandler::handle(exc);
|
||||||
dispatch(*it, _pErrorNotification);
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
ErrorHandler::handle();
|
||||||
}
|
}
|
||||||
else onTimeout();
|
|
||||||
}
|
}
|
||||||
onShutdown();
|
onShutdown();
|
||||||
}
|
}
|
||||||
@ -172,6 +204,12 @@ void SocketReactor::onTimeout()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SocketReactor::onIdle()
|
||||||
|
{
|
||||||
|
dispatch(_pIdleNotification);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SocketReactor::onShutdown()
|
void SocketReactor::onShutdown()
|
||||||
{
|
{
|
||||||
dispatch(_pShutdownNotification);
|
dispatch(_pShutdownNotification);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// SocketTest.cpp
|
// SocketTest.cpp
|
||||||
//
|
//
|
||||||
// $Id: //poco/svn/Net/testsuite/src/SocketTest.cpp#2 $
|
// $Id: //poco/1.3/Net/testsuite/src/SocketTest.cpp#2 $
|
||||||
//
|
//
|
||||||
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
|
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
|
||||||
// and Contributors.
|
// and Contributors.
|
||||||
@ -425,6 +425,18 @@ void SocketTest::testSelect2()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SocketTest::testSelect3()
|
||||||
|
{
|
||||||
|
Socket::SocketList readList;
|
||||||
|
Socket::SocketList writeList;
|
||||||
|
Socket::SocketList exceptList;
|
||||||
|
Timespan timeout(1000);
|
||||||
|
|
||||||
|
int rc = Socket::select(readList, writeList, exceptList, timeout);
|
||||||
|
assert (rc == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SocketTest::setUp()
|
void SocketTest::setUp()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -452,6 +464,7 @@ CppUnit::Test* SocketTest::suite()
|
|||||||
CppUnit_addTest(pSuite, SocketTest, testOptions);
|
CppUnit_addTest(pSuite, SocketTest, testOptions);
|
||||||
CppUnit_addTest(pSuite, SocketTest, testSelect);
|
CppUnit_addTest(pSuite, SocketTest, testSelect);
|
||||||
CppUnit_addTest(pSuite, SocketTest, testSelect2);
|
CppUnit_addTest(pSuite, SocketTest, testSelect2);
|
||||||
|
CppUnit_addTest(pSuite, SocketTest, testSelect3);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// SocketTest.h
|
// SocketTest.h
|
||||||
//
|
//
|
||||||
// $Id: //poco/svn/Net/testsuite/src/SocketTest.h#2 $
|
// $Id: //poco/1.3/Net/testsuite/src/SocketTest.h#2 $
|
||||||
//
|
//
|
||||||
// Definition of the SocketTest class.
|
// Definition of the SocketTest class.
|
||||||
//
|
//
|
||||||
@ -59,6 +59,7 @@ public:
|
|||||||
void testOptions();
|
void testOptions();
|
||||||
void testSelect();
|
void testSelect();
|
||||||
void testSelect2();
|
void testSelect2();
|
||||||
|
void testSelect3();
|
||||||
|
|
||||||
void setUp();
|
void setUp();
|
||||||
void tearDown();
|
void tearDown();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user