#ifndef SOCKETS_H #define SOCKETS_H ///////////////////////////////////////////////////////////////// // Sockets.h - C++ wrapper for C socket api // // ver 4.0 // // Jim Fawcett, CSE687 - Object Oriented Design, Spring 2015 // ///////////////////////////////////////////////////////////////// /* * ToDo: * - Fix network byte ordering * - Now works with loopbacks 127.0.0.1 and ::1 but doesn't work * with explicit ip addresses or machine names * - provide send and recv taking external buffer, perhaps array? * - write buffered recv which efficiently returns string or line * - reads and concatenates everything available into circular buffer * - parses out first string or line and moves start of buffer pointer * - to begining of next * - polish Socket, SocketConnecter, SocketListener * - complete all the move ctors and assignments * - finalize the class interfaces * - build front end, e.g., Sender and Receiver classes * - implement message facility: message class, sendMsg and recvMsg * - Add Manual and Maintenance pages */ #ifndef WIN32_LEAN_AND_MEAN // prevents duplicate includes of core parts of windows.h in winsock2.h #define WIN32_LEAN_AND_MEAN #endif #include // Windnows API #include // Windows sockets, ver 2 #include // support for IPv6 and other things #include // ip helpers #include #include #include #pragma warning(disable:4522) #pragma comment(lib, "Ws2_32.lib") #define DEFAULT_BUFLEN 512 #define DEFAULT_PORT "27015" ///////////////////////////////////////////////////////////////////////////// // SocketSystem class - manages loading and unloading Winsock library class SocketSystem { public: SocketSystem(); ~SocketSystem(); private: int iResult; WSADATA wsaData; }; ///////////////////////////////////////////////////////////////////////////// // Socket class // - used by server for client handling // - base for SocketConnecter and SocketListener classes class Socket { public: enum IpVer { IP4, IP6 }; using byte = char; using Block = std::vector < byte >; Socket(); Socket(::SOCKET); Socket(const Socket& s) = delete; Socket(Socket&& s); operator ::SOCKET() { return std::move(socket_); } Socket& operator=(const Socket& s) = delete; Socket& operator=(Socket&& s); virtual ~Socket(); void close(); bool send(const Block& blk); Block recv(); bool sendString(const std::string& str); std::string recvString(); size_t bytesWaiting(); bool waitForData(size_t timeToWait, size_t timeToCheck); bool shutDownSend(); bool shutDownRecv(); bool shutDown(); bool validState() { return socket_ != INVALID_SOCKET; } protected: WSADATA wsaData; ::SOCKET socket_; struct addrinfo *result = NULL, *ptr = NULL, hints; static const int recvbuflen = DEFAULT_BUFLEN; char recvbuf[recvbuflen]; int iResult; }; ///////////////////////////////////////////////////////////////////////////// // SocketConnecter class // - supports connecting to a SocketListener class SocketConnecter : public Socket { public: SocketConnecter() : Socket() {} SocketConnecter(const SocketConnecter& s) = delete; SocketConnecter(SocketConnecter&& s); SocketConnecter& operator=(const SocketConnecter& s) = delete; SocketConnecter& operator=(SocketConnecter& s); virtual ~SocketConnecter() {} bool connect(const std::string& ip, size_t port); }; ///////////////////////////////////////////////////////////////////////////// // SocketListener class // - listens for incoming connections // - each connection is handled on its own thread class SocketListener : public Socket { public: SocketListener(size_t port, IpVer ipv=IP6); SocketListener(const SocketListener& s) = delete; SocketListener(SocketListener&& s); SocketListener& operator=(const SocketListener& s) = delete; SocketListener& operator=(SocketListener& s); virtual ~SocketListener() {} template bool start(CallObj& co); void stop(); private: bool bind(); bool listen(); Socket accept(); std::atomic stop_ = false; size_t port_; }; #endif