TCPSocket.cc
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <signal.h>
#include "TCPSocket.h"
char *TCPSocket::ErrorMessage()
{
return szErrorMessage_;
}
unsigned long TCPSocket::getHostByName(const char *hostName)
{
struct hostent *hent;
hent = gethostbyname(hostName);
if (!hent)
return FALSE;
return *((unsigned long *)hent->h_addr);
}
int TCPSocket::getServiceByName(const char *ServiceName, const char *Protocol)
{
struct servent *sent;
sent = getservbyname(ServiceName, Protocol);
if (!sent)
return FALSE;
return ntohs(sent->s_port);
}
TCPSocket::TCPSocket()
:socket_(0), portNumber_(0), hostAddress_(0), initialized_(FALSE)
{
szErrorMessage_ = "";
}
TCPSocket::~TCPSocket()
{
Close();
}
int TCPSocket::init(const char *hostName, const char *serviceName)
{
hostAddress_ = TCPSocket::getHostByName(hostName);
if (!hostAddress_) {
szErrorMessage_ = "Failed to resolve host name";
return FALSE;
}
portNumber_ = TCPSocket::getServiceByName(serviceName, "tcp");
if (!portNumber_) {
portNumber_ = atoi(serviceName);
if (!portNumber) {
szErrorMessage_ = "Failed to resolve service name";
return FALSE;
}
}
initialized_ = TRUE;
return TRUE;
}
int TCPSocket::Connect()
{
struct sockaddr_in sin;
if (!initialized_) {
szErrorMessage_ = "Socket must be initialized before use";
return FALSE;
}
if (socket_) {
szErrorMessage_ = "Socket already exists. Call close before connect";
return FALSE;
}
socket_ = socket( AF_INET, SOCK_STREAM, 0 );
if (SOCKET_IS_INVALID(socket_)) {
szErrorMessage_ = "Couldn't create socket:";
return FALSE;
}
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(portNumber_);
sin.sin_addr.s_addr = hostAddress_;
if (connect(socket_, (struct sockaddr *)&sin, sizeof(struct sockaddr)) == -1) {
szErrorMessage_ = "Connect failed";
return FALSE;
} else
return TRUE;
}
int TCPSocket::Recv(char *buf, int *bufSize)
{
int n = *bufSize;
if (!initialized_) {
szErrorMessage_ = "Socket must be initialized before use";
return FALSE;
}
if (!socket_) {
szErrorMessage_ = "Socket does not exist, call connect first";
return FALSE;
}
if ((n = recv(socket_, buf, n, 0)) == -1) {
szErrorMessage_ = "ERROR: Call to recv failed";
*bufSize = -1;
return FALSE;
} else {
*bufSize = n;
return TRUE;
}
}
int TCPSocket::RecvAll(void **ppResult, long *pResultSize)
{
int iBufferSize = 1460;
char szBuffer[1460 +1];
int MoreToRead = TRUE;
char *szResultBuffer = NULL;
int iResultBufferSize = 0;
memset(szBuffer, 0, sizeof(szBuffer));
if (!initialized_) {
szErrorMessage_ = "Socket must be initialized before use";
return FALSE;
}
if (!socket_) {
szErrorMessage_ = "Socket does not exist, call connect first";
return FALSE;
}
while (MoreToRead || Poll(0, TRUE)) {
int n;
MoreToRead = FALSE;
if ((n = recv(socket_, szBuffer, iBufferSize, 0)) == -1) {
szErrorMessage_ = "recv ERROR: Call to recv failed";
return FALSE;
}
if (!szResultBuffer) {
szResultBuffer = new char[n+1];
memset(szResultBuffer, '\0', n+1);
} else {
char *szTmpBuffer = NULL;
szTmpBuffer = new char[iResultBufferSize + n+1];
memset(szTmpBuffer, '\0', iResultBufferSize + n+1);
memcpy(szTmpBuffer, szResultBuffer, iResultBufferSize);
delete szResultBuffer;
szResultBuffer = szTmpBuffer;
}
memcpy(szResultBuffer + iResultBufferSize, szBuffer, n);
iResultBufferSize += n;
if (n < iBufferSize)
break;
MoreToRead = TRUE;
}
(*ppResult) = szResultBuffer;
(*pResultSize) = iResultBufferSize;
if (iResultBufferSize == 0) {
szErrorMessage_ = "0 bytes received, connection was probobaly reset.";
return FALSE;
}
return TRUE;
}
int TCPSocket::Send(const char *Buffer, int BufferSize)
{
if (!initialized_) {
szErrorMessage_ = "Socket must be initialized before use";
return FALSE;
}
if (!socket_) {
szErrorMessage_ = "Socket does not exist, call connect first";
return FALSE;
}
// This writes exactly 1024 characters and the receiving end reads
// exactly 1024 bytes
int siz = (BufferSize > 1024) ? BufferSize : (1024+1);
char *pTemp = new char[siz+1];
memset(pTemp, 0, siz+1);
strncpy(pTemp, Buffer, BufferSize);
if (send(socket_, pTemp, siz, 0) == -1) {
szErrorMessage_ = "ERROR: Call to send failed";
delete [] pTemp;
return FALSE;
} else {
delete [] pTemp;
return TRUE;
}
}
int TCPSocket::Close()
{
close(socket_);
}
int TCPSocket::Poll(double Timeout, int rw)
{
fd_set fds, fdz;
struct timeval tv;
int n;
tv.tv_sec = (long) Timeout;
tv.tv_usec = (long) (1000000.0 * (Timeout - (double) tv.tv_sec));
FD_ZERO(&fdz);
FD_ZERO(&fds);
FD_SET(socket_, &fds);
n = select(socket_+1, rw ? &fds : &fdz, !rw ? &fds : &fdz, &fdz, &tv);
if (n < 0) {
szErrorMessage_ = "select() failed";
return FALSE;
}
if (n == 0) {
szErrorMessage_ = "Timeout waiting for socket";
return FALSE;
}
if (FD_ISSET(socket_, &fds))
return TRUE;
szErrorMessage_ = "Call to Poll succeeded but socket not ready?!?";
return FALSE;
}