Overview
Features
Download
Documentation
Community
Add-Ons & Services

Extending SocketAcceptor

Please post support and help requests here.

Extending SocketAcceptor

Postby electic » 03 Feb 2007, 19:20

Here is what I am trying to do. My company is evaluating POCO and we are making a small test project. Basically, we are getting X number of connections per hour and some of those incoming connections could be from the same IP address. So we are looking at the SocketReactor model that was presented in the example. The thing is that we would like to pass a ExpireCache object to the class that handles the onReadable events, etc. Here is my code:

Code: Select all

template
class TorrentConnectionAcceptor : public SocketAcceptor
{
   
public:
   TorrentConnectionAcceptor(ServerSocket &socket, SocketReactor &reactor)
      : SocketAcceptor(socket, reactor),
      mainSocket(socket),
      mainReactor(reactor)
   {
   }
      
   virtual ServiceHandler* createServiceHandler(StreamSocket& socket)
   {
      return new TorrentProtocolHandler(socket, mainReactor, &cache);
   }
      
private:
   ExpireCache cache;
   ServerSocket &mainSocket;
   SocketReactor &mainReactor;
};
 


The constructor in TorrentProtocolHandler.cpp:

Code: Select all

TorrentProtocolHandler(StreamSocket& socket, SocketReactor& reactor, ExpireCache *cache);


In main.cpp when I call this:

Code: Select all

TorrentConnectionAcceptor acceptor(svs, reactor);


I get the following compiler errors:

usr/local/include/Poco/Net/SocketAcceptor.h: In member function 'ServiceHandler* Poco::Net::SocketAcceptor::createServiceHandler(Poco::Net::StreamSocket&) [with ServiceHandler = TorrentProtocolHandler]':
/usr/local/include/Poco/Net/SocketAcceptor.h:144: instantiated from 'void Poco::Net::SocketAcceptor::onAccept(Poco::Net::ReadableNotification*) [with ServiceHandler = TorrentProtocolHandler]'
/usr/local/include/Poco/Net/SocketAcceptor.h:136: instantiated from 'void Poco::Net::SocketAcceptor::unregisterAcceptor() [with ServiceHandler = TorrentProtocolHandler]'
/usr/local/include/Poco/Net/SocketAcceptor.h:111: instantiated from 'Poco::Net::SocketAcceptor::~SocketAcceptor() [with ServiceHandler = TorrentProtocolHandler]'
/Users/Electic/Documents/Source Code/Torrent Rovers/Torrent Listener/TorrentConnectionAcceptor.h:10: instantiated from here
/usr/local/include/Poco/Net/SocketAcceptor.h:153: error: no matching function for call to 'TorrentProtocolHandler::TorrentProtocolHandler(Poco::Net::StreamSocket&, Poco::Net::SocketReactor&)'
/Users/Electic/Documents/Source Code/Torrent Rovers/Torrent Listener/TorrentProtocolHandler.h:18: note: candidates are: TorrentProtocolHandler::TorrentProtocolHandler(Poco::Net::StreamSocket&, Poco::Net::SocketReactor&, Poco::ExpireCache*)
/Users/Electic/Documents/Source Code/Torrent Rovers/Torrent Listener/TorrentProtocolHandler.h:16: note: TorrentProtocolHandler::TorrentProtocolHandler(const TorrentProtocolHandler&)

So for some reason, the base class is not being overridden because the compiler still wants to go here and check this function in SocketAcceptor.h:

Code: Select all

   virtual ServiceHandler* createServiceHandler(StreamSocket& socket)
      /// Create and initialize a new ServiceHandler instance.
      ///
      /// Subclasses can override this method.
   {
      return new ServiceHandler(socket, *_pReactor);
   }


Does any one have an example of successfully overriding this class or see what I am doing wrong? Is the SocketReactor example a good implementation idea for large amount of incoming connections or is a TCPServer a better choice and is there an example of the TCPServer with a reactor attached?
electic
 
Posts: 48
Joined: 30 Jan 2007, 20:28

Re: Extending SocketAcceptor

Postby guenter » 04 Feb 2007, 17:29

Hi,

your implementation of TorrentConnectionAcceptor is basically correct. However, you also most provide a two-argument constructor for TorrentProtocolHandler:

Code: Select all

TorrentProtocolHandler::TorrentProtocolHandler(StreamSocket& socket, SocketReactor& reactor)
{
    poco_bugcheck();
}


The reason for this is as follows: The compiler needs to instantiate both the base class template SocketAcceptor and your subclass template TorrentConnectionAcceptor. When a class template is instantiated, the compiler must also instantiate all virtual member functions, regardless whether they are actually used or not, because the virtual function table must be populated. Therefore, the compiler instantiates SocketAcceptor: :createServiceHandler(). To instantiate that, it needs a two argument constructor for TorrentProtocolHandler.
Since this two argument constructor is never actually called, you can provide a dummy implementation with a guard (bugcheck) that checks against accidentally calling it.

Instead of providing the two argument constructor, you could also provide a default value (0) for the third argument of the three argument constructor. When I think about it, this might actually be the cleaner solution.

Regarding SocketReactor vs. TCPServer:

TCPServer uses a thread-per-connection model. Therefore, if you have lots of long-running connections, you'll end up with lots of concurrent threads, which might be a Bad Thing to have. So I guess for your application the SocketReactor is the better choice.
guenter
 
Posts: 1110
Joined: 11 Jul 2006, 16:27
Location: Austria

Re: Extending SocketAcceptor

Postby electic » 05 Feb 2007, 18:49

Thanks guenter, I fixed it based on your suggestions and it worked great. I did try a TCPServer though and I think that might be best. In my TCPServer example, I just read 80 bytes and return from the function right away. But here is the issue. When I run the example, my processor usage goes to 100 percent right after I receive the first connection. I compiled it on OS X Tiger. Are there any known issues for this?
electic
 
Posts: 48
Joined: 30 Jan 2007, 20:28

Re: Extending SocketAcceptor

Postby electic » 06 Feb 2007, 04:46

Nevermind, I fixed it.
electic
 
Posts: 48
Joined: 30 Jan 2007, 20:28


Return to Support

Who is online

Users browsing this forum: No registered users and 1 guest