#ifndef COMM_H #define COMM_H ///////////////////////////////////////////////////////////////////////// // comm.h - communication classes, used by client and server // // ver 1.3 to setup and use message-passing communications // // // // Language: Visual C++, ver 6.0 // // Platform: Dell Dimension 8100, Windows 2000 Pro, SP1 // // Application: CSE691/791 help // // Author: Jim Fawcett, CST 2-187, Syracuse University // // (315) 443-3948, jfawcett@twcny.rr.com // ///////////////////////////////////////////////////////////////////////// /* Module Operations ================= This module provides commClt and commSvr classes that provide socket- based communication services to a client/server pair. These classes are based on sockClt and sockSvr classes. commClt and commSvr simply wrap the socks classes so that users do not have to direcly handle queues, worry about synchronization, or any other multi-threading issues. To see how to use this module to establish socket-based communication between remote machines, look at the two main functions in comm.cpp. Public Interface ================ commClt client("127.0.0.1",1024); message sndMsg(message::text,"this is a test"); client.postMessage(sndMsg); message rcvMsg; client.getMessage(rcvMsg); commSvr server(1025); message rcvMsg; int clientID; server.getMessage(clientID,rcvMsg); message sndMsg(message::text,"this is the text"); server.postMessage(clientID,rcvMsg); The commSvr users must return the clientID with a response to some message. Also, the user must return all quit messages to help the client shut down properly. */ // ///////////////////////////////////////////////////////////////////////// // Build Process // ///////////////////////////////////////////////////////////////////////// // Required Files: // // comm.h comm.cpp, socks.h, socks.cpp, connMgr.h, connMgr.cpp, // // msgHnd.h, mshHnd.cpp, xmlTran.h, xmlTran.cpp, // // mtqueue.h, mtqueue.cpp, nodePool.h, nodePool.cpp, // // lockingPtr.h, lockingPtr.cpp, sysUtils.h, sysUtils.cpp, // // thrdsWithProc.h, thrdsWithProc.cpp // // // // Compiler command: // // cl /GX /MTd /DTEST_COMM_SERVER comm.cpp socks.cpp connMgr.cpp \ // // msgHnd.cpp xmlTran.cpp mtqueue.cpp nodePool.cpp \ // // lockingPtr.cpp sysUtils.cpp thrdsWithProc.cpp wsock32.lib // // // ///////////////////////////////////////////////////////////////////////// /* Maintenance History =================== ver 1.3 : 21 Nov 01 - made cosmetic changes to the test stubs - now read an IP address string from the client command line. ver 1.2 : 19 Nov 01 - added a working server. Not very much needed to be added, since most of this functionality was already part of the socks module that this comm module uses to do all socket handling. ver 1.1 : 18 Nov 01 - released with just the client working, to help CSE784 Comm team with their implementation. ver 1.0 : 12 Nov 01 - not yet released Planned Modifications ===================== - explore possibility of providing notifications, using the observer design pattern */ // #include #include "socks.h" #include "msgHnd.h" #include "connMgr.h" #include "mtqueue.h" #include "lockingPtr.h" #include "thrdsWithProc.h" const int cltSendQlock = 333; const int cltRecvQlock = 334; typedef GlobalMutex cltSendQlocker; typedef GlobalMutex cltRecvQlocker; typedef lockingPtr,cltSendQlocker> cltSendQlp; typedef lockingPtr,cltRecvQlocker> cltRecvQlp; ///////////////////////////////////////////////////////////////////// // define client send thread processing class cltSendProc : public processing { public: cltSendProc(sockClt &client) : _client(client) { } volatile mtqueue& sendQ() { return _sendQ; } void run() { cltSendQlocker sLock; safeOut sout(std::cout); while(1) { if(cltSendQlp(_sendQ,sLock)->length() > 0) { message sndMsg = cltSendQlp(_sendQ,sLock)->deQ(); _client << sndMsg.serialize(); if(sndMsg.body() == "quit") { sout << "\n client send thread shutting down"; return; } } ::Sleep(50); } } private: sockClt &_client; volatile mtqueue _sendQ; }; // ///////////////////////////////////////////////////////////////////// // define client receive thread processing class cltRecvProc : public processing { public: cltRecvProc(sockClt &client) : _client(client) { _precvQ = &_recvQ; } volatile mtqueue& recvQ() { return _recvQ; } volatile mtqueue* precvQ() { return _precvQ; } void run() { std::string rcvMsg; safeOut sout(std::cout); int bytes; do { std::string rcvMsg, head, remainder; bytes = _client.recv(head,message::headSize); if(bytes == 0) { sout << "\n socket read error in client recv thread"; break; } int bytesLeft = message::bytesToRead(head); bytes = _client.recv(remainder,bytesLeft); if(bytes == 0) { sout << "\n socket read error in client recv thread"; break; } rcvMsg = head + remainder; message recvd(rcvMsg); if(_client.good()) { cltRecvQlocker lock; int len = cltRecvQlp(_recvQ,lock)->length(); cltRecvQlp(_recvQ,lock)->enQ(recvd); } if(recvd.body() == "quit") { sout << "\n client receiver thread shutting down"; return; } } while(_client.good()); sout << "\n client receiver thread shutting down"; } private: sockClt &_client; volatile mtqueue _recvQ; volatile mtqueue *_precvQ; }; // ///////////////////////////////////////////////////////////////////// // declare commClt class class commClt { public: commClt(); ~commClt(); bool connect(const char *server, int port); bool connect(std::string &server, int port); void postMessage(message &msg); bool getMessage(message &msg); private: sockClt _client; cltSendProc _sendProc; cltRecvProc _recvProc; thread _sender; thread _recver; volatile mtqueue *_pRecvQ; }; // //const int connMgrLock = 101; defined in connMgr.h //const int svrSendQlock = 335; " " " //const int svrRecvQlock = 336; " " " typedef GlobalMutex cmlocker; typedef GlobalMutex svrSendQlocker; typedef GlobalMutex svrRecvQlocker; typedef lockingPtr connMgrlp; typedef lockingPtr,svrSendQlocker> svrSendQlp; typedef lockingPtr,svrRecvQlocker> svrRecvQlp; /////////////////////////////////////////////////////////////// // define processing for server's processing thread // // Simply starts server class serverProc : public processing { public: serverProc() { } virtual void run() { safeOut sout(std::cout); sout << "\n running server\n"; sockSvr server(1024); server.start(); } }; ///////////////////////////////////////////////////////////////////// // declare commSvr class class commSvr { public: commSvr(int port); ~commSvr(); void postMessage(int clientID, const message &msg); bool getMessage(int &clientID, message &msg); private: sockSvr _server; connectionMgr _connMgr; serverProc _serverProc; thread _serverThread; }; #endif