///////////////////////////////////////////////////////////////////// // socks.cpp - socket client and multi-threaded server // // prototype for project #2 // // ver 1.1 // // Language: Visual C++, ver 6.0, SP 5 // // Platform: Dell Dimension 8100, Win 2000 Pro, SP 2 // // Application: CSE691/791 - SWM&A Demonstration // // Author: Jim Fawcett, CST 2-187, Syracuse Univ // // (315) 443-3948, jfawcett@twcny.rr.com // ///////////////////////////////////////////////////////////////////// #include #include #include "socks.h" using namespace std; CRITICAL_SECTION sockSvr::_cs; //----< constructor >------------------------------------------------ sockClt::sockClt() { // load version 1.1 of winsock dll WORD wVersionRequested = MAKEWORD(1,1); // requesting version 1.1 WSAData wData; // startup data filled // by WSAStartup int err = WSAStartup(wVersionRequested, &wData); if(err == SOCKET_ERROR) { int errType = WSAGetLastError(); cout << "\n initialization error type: " << errType << "\n\n"; } // create TCP/IP socket object _client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); } // //----< attempt to connect to a server >----------------------------- bool sockClt::connectTo(address &addr) { // connect to server on specified address and port // - note the IP address 127.0.0.1 refers to host machine int port = 1024; // user port struct hostent *serverHostent; serverHostent = gethostbyname("Lusitania"); SOCKADDR_IN tcpAddr; tcpAddr.sin_family = AF_INET; // TCP/IP tcpAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // host machine tcpAddr.sin_port = htons(port); // server port int err = ::connect(_client, (sockaddr*)&tcpAddr, sizeof(tcpAddr)); if(err == SOCKET_ERROR) { int errType = WSAGetLastError(); cout << "\n connection error type: " << errType << "\n\n"; return false; } return true; } //----< attempt to connect to a server >----------------------------- bool sockClt::connectTo(const char *s) { return connectTo(string(s)); } //----< destructor >------------------------------------------------- sockClt::~sockClt() { closesocket(_client); WSACleanup(); } // //----< insertion operator >----------------------------------------- sockClt& sockClt::operator<<(std::string &s) { int bytesSent = send(s.c_str()); if(bytesSent != s.size()) throw "transmission error in sockClt::operator<<(std::string &s)"; return *this; } //----< insertion operator >----------------------------------------- sockClt& sockClt::operator<<(const char *s) { return operator<<(string(s)); } //----< extraction operator >---------------------------------------- sockClt& sockClt::operator>>(std::string &s) { return *this; } //----< send a block of bytes through socket connection >------------ // // attempts to guarantee that all bytes are sent // int sockClt::send(const char *block) { const int sendRetries = 100; int blockLen = strlen(block); int bytesSent; int bytesLeft = blockLen; int blockIndx = 0; int count = 0; while(bytesLeft > 0) { bytesSent = ::send(_client,&block[blockIndx],bytesLeft,0); if(bytesSent == SOCKET_ERROR) { Sleep(50); ++count; } if(count==sendRetries) throw "send failed after 100 retries",__FILE__,__LINE__; bytesLeft -= bytesSent; blockIndx += bytesSent; } return blockLen; } // //----< constructor >------------------------------------------------ sockSvr::sockSvr() { // load version 1.1 of winsock dll WORD wVersionRequested = MAKEWORD(1,1); // requesting version 1.1 WSAData wData; // startup data filled // by WSAStartup int err = WSAStartup(wVersionRequested, &wData); if(err == SOCKET_ERROR) { int errType = WSAGetLastError(); cout << "\n initialization error type: " << errType << "\n\n"; } InitializeCriticalSection(&_cs); } //----< destructor >------------------------------------------------- sockSvr::~sockSvr() { DeleteCriticalSection(&_cs); closesocket(_listener); WSACleanup(); } // //----< start up server >-------------------------------------------- void sockSvr::start() { // create TCP/IP socket object to listen for connection requests _listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // bind listner socket to specific port and network interface int port = 1024; SOCKADDR_IN tcpAddr; tcpAddr.sin_family = AF_INET; // TCP/IP tcpAddr.sin_port = htons(port); // listening port tcpAddr.sin_addr.s_addr = INADDR_ANY; // listen over every network interface int err = bind(_listener, (SOCKADDR*)&tcpAddr, sizeof(tcpAddr)); if(err == SOCKET_ERROR) { int errType = WSAGetLastError(); cout << "\n initialization error type: " << errType << "\n\n"; return; // errType; } // listen for incoming connection requests int backLog = 10; err = ::listen(_listener, backLog); if(err == SOCKET_ERROR) { int errType = WSAGetLastError(); cout << "\n initialization error type: " << errType << "\n\n"; return; //errType; } // cout << "\n waiting for incoming request"; // block until a connection is established int size = sizeof(tcpAddr); while(1) { SOCKET toClient = accept(_listener, (SOCKADDR*)&tcpAddr, &size); if(toClient == INVALID_SOCKET) break; EnterCriticalSection(&_cs); cout << "\n established connection with: " << inet_ntoa(tcpAddr.sin_addr) << ":" << ntohs(tcpAddr.sin_port) << endl; LeaveCriticalSection(&_cs); // got connection so spawn thread to read transferred data unsigned int threadID; HANDLE hThread = (HANDLE)_beginthreadex( NULL, 0, threadProc, &toClient, 0, &threadID ); CloseHandle(hThread); } } //----< attempt to connect to client and receive messages >---------- bool sockSvr::handleConnection(connectionHandler &ch) { return true; } // //----< client connection thread processing >------------------------ unsigned int __stdcall sockSvr::threadProc(void *pArgs) { SOCKET *pSock = (SOCKET*)pArgs; string save; const int bufSize = 1024; char buffer[bufSize]; int bytes, count=0; do { bytes = recv(*pSock,buffer,bufSize-1,0); buffer[bytes] = '\0'; save = buffer; if(bytes > 0) { EnterCriticalSection(&_cs); cout << save.c_str(); cout.flush(); LeaveCriticalSection(&_cs); } } while(bytes != 0 && bytes != SOCKET_ERROR); if(bytes == SOCKET_ERROR) { int errType = WSAGetLastError(); EnterCriticalSection(&_cs); cout << "\n receive error type: " << errType << "\n\n"; LeaveCriticalSection(&_cs); } closesocket(*pSock); return 0; } // //----< test stub >-------------------------------------------------- #ifdef TEST_SOCKS_CLIENT void main(int argc, char *argv[]) { cout << "\n running client\n"; try { sockClt client; if(!client.connectTo("127.0.0.1")) throw "socket connection error"; if(argc > 1) { int i=1; cout << " "; while(i < argc) client << " " << argv[i++]; } else { client << "this is a string\n"; client << "and another\n"; } } catch(const char *msg) { cout << "\n " << msg << "\n\n"; } catch(...) { cout << "\n unknown error type\n\n"; } } #endif #ifdef TEST_SOCKS_SERVER void main() { cout << "\n running server\n"; try { sockSvr server; server.start(); } catch(...) { cout << "\n can't create server - is there one already running?\n\n"; } } #endif