///////////////////////////////////////////////////////////////////// // SocketServer.cpp - Provides listener that spawns client-handler // // ver 1.1 threads // // Language: Visual C++, 2005 // // Platform: Dell Dimension 9150, Windows XP Pro, SP 2.0 // // Application: Utility for CSE687 and CSE775 projects // // Author: Jim Fawcett, Syracuse University, CST 2-187 // // (315) 443-3948, jfawcett@twcny.rr.com // ///////////////////////////////////////////////////////////////////// #include #include #include "SocketServer.h" #include "diagnostics.h" ///////////////////////////////////////////////////////////////////// // SocketServer processing class listenProc : public processing { public: listenProc(SocketServer* pServer) : pServer_(pServer), listening(true) {} ~listenProc() { Trace("destroying listenProc instance"); for(size_t i=0; ipListener->waitForConnect()); if(pSocket->error()) { Trace("returned from waitForConnect() with error"); break; } pSocket->setTerminator(""); socketCollection.push_back(pSocket); Trace("starting child thread"); IProc* pHandler = pClientHandler_->clone(); pHandler->acceptSocket(pSocket); thread* pClientHandlerThread = CreateThreadOnHeap(pHandler); pClientHandlerThread->start(); pServer_->tp.add(pClientHandlerThread); } pServer_->pListener->stop(); } void stop() { listening = false; } private: IProc* pClientHandler_; SocketServer* pServer_; std::vector socketCollection; bool listening; }; // //----< start server listening for connections >--------------------- void SocketServer::start(int port) { Trace("starting server"); pListener = new SocketListener(port); listenProc* pProc = new listenProc(this); if(pHandler_ == 0) throw std::exception("no registered client handler"); pProc->registerClientHandler(pHandler_); pListenerThread = CreateThreadOnHeap(pProc); pListenerThread->start(); } //----< stop server's listening >------------------------------------ void SocketServer::stop(int wait) { Trace("stopping server"); // won't stop until at least one client thread has started while(tp.size() == 0) { if(wait > -1) { ::Sleep(wait); break; } else { ::Sleep(100); } } tp.waitAll(); pListener->stop(); Trace("finished waiting for threads to complete"); } //----< register client handler with SocketServer >------------------ void SocketServer::registerClientHandler(IProc* pHandlerProc) { pHandler_ = pHandlerProc; } // ///////////////////////////////////////////////////////////////////// // demonstration client handler just displays message class defaultClientHandlerProc : public IProc { public: defaultClientHandlerProc() { Trace("creating client handler"); } ~defaultClientHandlerProc() { Trace("destroying client handler"); } IProc* clone() { Trace("creating client handler"); return new defaultClientHandlerProc; } /////////////////////////////////////////////////////////// // no locks needed since each client thread has its own // clone of this class void run() { while(true) { // Trace("receiving message in defaultClientHandlerProc"); msg = pSocket_->recv(); done = (msg == "quit"); sout << locker << "\n " << msg << unlocker; if(done) break; } pSocket_->disconnect(); } private: std::string msg; bool done; }; // //----< test stub >-------------------------------------------------- #ifdef TEST_SOCKETSERVER ///////////////////////////////////////////////////////////////////// // test client - creates 10 messages and sends each with a // short sleep between each message class TestClientProcessing : public processing { public: TestClientProcessing(const std::string& machine, int sleepTime) : sleepTime_(sleepTime) { client.setTerminator(""); client.connect(machine,4048); #ifdef TRACE std::string lip = client.getLocalIP(); int lport = client.getLocalPort(); std::string rip = client.getRemoteIP(); int rport = client.getRemotePort(); std::string msg = "local connection: " + lip + ":" + ToString(lport); Trace(msg); msg = "remote connection: " + rip + ":" + ToString(rport); Trace(msg); #endif } void run() { for(int i=0; i<10; ++i) { msg = "message #"; msg += ToString(i) + ""; // Trace("client sending message"); if(!client.send(msg)) break; ::Sleep(sleepTime_); } msg = "quit"; client.send(msg); } private: int sleepTime_; Socket client; std::string msg; }; //----< entry point for test stub >---------------------------------- void main() { std::cout << "\n Testing SocketServer"; std::cout << "\n ======================\n"; try { SocketServer server; defaultClientHandlerProc Handler; server.registerClientHandler(&Handler); server.start(4048); TestClientProcessing tcp1("columbia",100); thread client1Thread(&tcp1); TestClientProcessing tcp2("columbia",50); thread client2Thread(&tcp2); client1Thread.start(); client2Thread.start(); server.stop(); sout << "\n\n"; EnterKeyToWait(); } catch(std::exception& ex) { std::cout << "\n " << ex.what() << "\n\n"; } } #endif