#30 - SDL_NET TCP Socket Class
Date: 2018-10-13 12:00 - C++
Class to wrap a TCP socket in a class with methods to read and write common data types.
// TCPSocket.h
#ifndef _TCPSOCKET__H_
#define _TCPSOCKET__H_
#include <SDL/SDL_net.h>
#include "NetAddress.h"
#define checkError(f) if((f) <= 0) throw std::string(SDLNet_GetError())
class TCPSocket {
bool _isServer;
TCPsocket _socket;
SDLNet_SocketSet _socketSet;
friend class Server;
TCPSocket(TCPsocket socket);
public:
TCPSocket();
TCPSocket(NetAddress& addr);
void connect(NetAddress& addr);
TCPSocket* accept();
void close();
unsigned int avalible();
// READ
std::string readString();
unsigned int readUInt() { unsigned int v; checkError(SDLNet_TCP_Recv(_socket, &v, sizeof(v))); return v; }
unsigned short readUShort() { unsigned short v; checkError(SDLNet_TCP_Recv(_socket, &v, sizeof(v))); return v; }
unsigned char readUChar() { unsigned char v; checkError(SDLNet_TCP_Recv(_socket, &v, sizeof(v))); return v; }
int readInt() { int v; checkError(SDLNet_TCP_Recv(_socket, &v, sizeof(v))); return v; }
short readShort() { short v; checkError(SDLNet_TCP_Recv(_socket, &v, sizeof(v))); return v; }
char readChar() { char v; checkError(SDLNet_TCP_Recv(_socket, &v, sizeof(v))); return v; }
float readFloat() { float v; checkError(SDLNet_TCP_Recv(_socket, &v, sizeof(v))); return v; }
double readDouble() { double v; checkError(SDLNet_TCP_Recv(_socket, &v, sizeof(v))); return v; }
int readCustom(void* data, unsigned int length) { int recv = 0; checkError(recv = SDLNet_TCP_Recv(_socket, data, length)); return recv; }
// WRITE
void writeString(std::string str) { writeUShort((unsigned short)str.length()); checkError(SDLNet_TCP_Send(_socket, str.c_str(), str.length())); }
void writeUInt(unsigned int val) { checkError(SDLNet_TCP_Send(_socket, &val, sizeof(val))); }
void writeUShort(unsigned short val) { checkError(SDLNet_TCP_Send(_socket, &val, sizeof(val))); }
void writeUChar(unsigned char val) { checkError(SDLNet_TCP_Send(_socket, &val, sizeof(val))); }
void writeInt(int val) { checkError(SDLNet_TCP_Send(_socket, &val, sizeof(val))); }
void writeUShort(short val) { checkError(SDLNet_TCP_Send(_socket, &val, sizeof(val))); }
void writeChar(char val) { checkError(SDLNet_TCP_Send(_socket, &val, sizeof(val))); }
void writeFloat(float val) { checkError(SDLNet_TCP_Send(_socket, &val, sizeof(val))); }
void writeDouble(double val) { checkError(SDLNet_TCP_Send(_socket, &val, sizeof(val))); }
void writeCustom(void* data, unsigned int length) { checkError(SDLNet_TCP_Send(_socket, data, length)); }
virtual ~TCPSocket();
};
#endif
// TCPSocket.cpp
#include "TCPSocket.h"
TCPSocket::TCPSocket(TCPsocket socket) : _socket(socket), _socketSet(NULL), _isServer(false) {
_socketSet = SDLNet_AllocSocketSet(1);
}
TCPSocket::TCPSocket() : _socket(NULL), _socketSet(NULL), _isServer(false) {
_socketSet = SDLNet_AllocSocketSet(1);
}
TCPSocket::TCPSocket(NetAddress& addr) : TCPSocket() {
connect(addr);
}
void TCPSocket::connect(NetAddress& addr) {
IPaddress* ipAddr = addr.getAddress();
_isServer = (ipAddr->host == INADDR_ANY || ipAddr->host == INADDR_NONE);
if((_socket = SDLNet_TCP_Open(ipAddr)) == NULL)
throw std::string("TCPSocket error: SDL_Net: " + std::string(SDLNet_GetError()));
SDLNet_TCP_AddSocket(_socketSet, _socket);
}
TCPSocket* TCPSocket::accept() {
TCPsocket client = NULL;
if(!_isServer) {
throw std::string("TCPSocket error: Not a server! Can't call accept()");
}
if (avalible() == 0 || !SDLNet_SocketReady(_socket)) {
return NULL;
}
if((client = SDLNet_TCP_Accept(_socket)) == NULL) {
SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags::SDL_MESSAGEBOX_INFORMATION, "ERROR", SDLNet_GetError(), NULL);
return NULL;
}
return new TCPSocket(client);
}
void TCPSocket::close() {
if (_socket != NULL) {
SDLNet_TCP_DelSocket(_socketSet, _socket);
SDLNet_TCP_Close(_socket);
_socket = NULL;
}
}
unsigned int TCPSocket::avalible() {
return SDLNet_CheckSockets(_socketSet, -1);
}
std::string TCPSocket::readString() {
unsigned short size = readUShort();
char* tmp = new char[size + 1];
int read = readCustom(tmp, size);
tmp[read] = 0;
std::string str(tmp);
delete[] tmp;
return str;
}
TCPSocket::~TCPSocket() {
close();
if (_socketSet != NULL) {
SDLNet_FreeSocketSet(_socketSet);
}
}