// CDXConnection - TCP/IP Connection and communication library // Author : Jimb Esser // Date : 1-28-1 // Version : 1.0 // Make sure to link with wsock32.lib and to set // C++ Code Generation to Multithreaded (/MT) #ifndef _CDXCONNECTION_H #define _CDXCONNECTION_H #include "bsd2win.h" #define TAG_RAW 0 // For raw data #define TAG_CHAT 1 // For a text/chat message #define TAG_NODEANNOUNCE 2 // When the server announces the node number to the client #define NODE_SERVER 0 // Pass this in to iNodeNum to send to the server if we're a client #define NODE_ALL -1 // Pass this in to send to all nodes (server only) #define MAX_CONNECTIONS 256 // Maximum number of connections to allocate space for pointers to sockets (only 4 bytes each) #define MAX_BUFFER 256 // Maximum number of bufferrs to create, any after this is lost class CDXConnection { public: CDXConnection(); // Default constructor ~CDXConnection(); // Default destructor /********** * BASICS * (enough to make a chat program) **********/ // Host Specific: /* CreateHost - needs to be called to make this connection object a server. */ HRESULT CreateHost(); /* Listen - the second step in creating a server. After starting the server listening, it will accept connections indefinitely unless you call stopAcceptingConnections() or setMaxConnections() iPort - The port to accept connections on. The clients must also be using the same port to connect. */ HRESULT Listen(unsigned short iPort); /* getNumConnections - returns the current number of clients connected */ int getNumConnections() { return m_iNumConnections; } // Client Specific: /* CreateClient - needs to be called to make this connection object a client. */ HRESULT CreateClient(); /* Connect - attempts to connect to a server at the given address and port. The server must already be initialized and listening. */ HRESULT Connect(char *addr, unsigned short iPort); /* StillConnected - returns whether or not we're still connected to the server */ bool StillConnected() { return m_bConnected;} // Returns false if a connection is lost /* getNodeNum - retrieves the node number that the server assigned to the client when it connected. */ int getNodeNum() { return m_iNodeNum; } // For both: /* isDataReady - returns true if there is data ready to be read in */ bool isDataReady(); /* getData - reads 1 packet of data. getData will fail if the packet size is larger than iMaxSize or if there is any type of network error, including the client sending the data dropping it's connection. iNodeNum - if we are calling this from the server, the node of the client that sent the data will be returned in this variable. If we are calling this from a client, this should be 0. data - this points to a buffer to store the incoming data iMaxSize - the size of the data buffer - the largest amount that can be allowed to be read in. iNumRead - the count of bytes read in will be return here. iTag (optional) - if you are tagging your data the tag will be returned here. Note: isDataReady() must return true for getData to succeed */ HRESULT getData(int &iNodeNum, char *data, int iMaxSize, int &iNumRead, unsigned char *iTag = NULL); /* sendData - sends 1 packet of data. sendData will fail if there is any type of network error, including the client dropping it's connection. iNodeNum - if we are calling this from a client, this should be NODE_SERVER (0). Clients cannot send to other clients, since this is not a peer-to-peer model. If we are calling this from the server, the node of the client that we want to send the data to, or NODE_ALL to send the packet to all of the connected clients. data - this points to the data to send iSize - the size of the data to be sent iTag (optional) - allows you to attach a tag to the data indicating what type of data you are sending. This makes it easy to discriminate between different types of messages that will be passed between the client and server. Note: isDataReady() must return true for getData to succeed */ HRESULT sendData(int iNodeNum, const char *data, int iSize, unsigned char iTag = TAG_RAW); /************************** * Advanced Functionality * **************************/ // Server: /* stopAcceptingConnections - tells the server not to accept any more connections. To start accepting connections again, a call to Listen must be made. */ void stopAcceptingConnections(); /* setMaxConnections - sets the maximum number of connections to accept before stopping listening. When this number is reached it will not accept any more connections unless Listen is called again *even* if some of the current connections drop out. */ void setMaxConnections(int iMaxConnections) { m_iMaxConnections = iMaxConnections; } /* m_bConnectionLost - this flag is set to true when a connection has dropped from the server. */ bool m_bConnectionLost; // Set to true when someone has dropped out private: // Server: int m_iNumConnections; SOCKET m_listenSocket; SOCKET m_Clients[MAX_CONNECTIONS]; unsigned long m_ulThread; bool m_bCreatedServer; bool m_bAcceptingConnections; int m_iMaxConnections; fd_set m_readyfds; // This set contains uptodate info on what sockets are ready for reading friend void ListenThread(void * dummy); // The subthread for listening for new connections // Client: bool m_bConnected; int m_iNodeNum; bool m_bCreatedClient; SOCKET m_clientSocket; // Both: struct sockaddr_in m_SockAddr; char * m_Buffer[MAX_BUFFER]; int m_iNumBuffers; int m_iCurBuffer; friend void BufferThread(void * dummy); // The subthread that reads all incoming data and buffers it int disableTCPdelay(SOCKET s); // disables the 200ms "naggling" on TCP sockets that causes delays int readFromSocket(SOCKET s, char *dest, int bytesToRead); }; #endif