Socket.cpp 4.31 KB
/** @file 
* \brief Fichero de implementación de la clase Socket
* \author Imanol Barba Sabariego
* \date 13/06/2013
*
* En este fichero se implementan los métodos de la clase Socket definidos en Socket.h
*/
#include "Socket.h"
#include "SocketException.h"
#include <sstream>
#include <strings.h>
#include <cstdlib>
#include <netinet/tcp.h>

using namespace std;

Socket::Socket()
{
        sock = -1;
}

int Socket::getSock()
{
        return sock;
}

void Socket::Create()
{
    int optval = 1;
    if((sock = socket(AF_INET, SOCK_STREAM, 0)) <= 0)
    {
    	throw SocketException ( "TCP: Could not create socket" );
    }
    setsockopt(sock,SOL_SOCKET,SO_KEEPALIVE,&optval,sizeof optval);
    setsockopt(sock, SOL_TCP, TCP_NODELAY, &optval, sizeof optval);
}

void Socket::Bind(string address, int port)
{
    sockAddr.sin_family = AF_INET;
    sockAddr.sin_port = htons(port);
    sockAddr.sin_addr.s_addr = inet_addr(address.c_str());
    if(bind(sock, (struct sockaddr *)&sockAddr, sizeof(struct sockaddr)) != 0)
    {
    	stringstream sstream;
    	sstream <<  "TCP: Could not bind to address " << address << " on port " << port;
    	throw SocketException ( sstream.str() );
    }
}

void Socket::Listen(int backlog)
{
    if(listen(sock, backlog) != 0)
    {
    	throw SocketException ( "TCP: Could not listen to socket"  );
    }
}

void Socket::Accept(Socket &clientSock)
{
    int size = sizeof(struct sockaddr);
    clientSock.sock = accept(sock,(struct sockaddr *)&clientSock.sockAddr, (socklen_t *)&size);
    if(clientSock.sock == -1)
    {
    	throw SocketException ( "TCP: Could not accept incoming connection" );
    }
}

void Socket::Connect(string hostname, int port)
{
    struct in_addr *addr_ptr;
    struct hostent *hostPtr;
    string add;
    hostPtr = gethostbyname(hostname.c_str());
    if(hostPtr == NULL)
    {
    	throw SocketException (string("Could not resolve hostname ").append(hostname));
    }
    addr_ptr = (struct in_addr *)*hostPtr->h_addr_list;
    add = inet_ntoa(*addr_ptr);
    if(add == "")
    {
    	throw SocketException ( "Invalid address" );
    }
    struct sockaddr_in newSockAddr;
    newSockAddr.sin_family = AF_INET;
    newSockAddr.sin_port = htons(port);
    newSockAddr.sin_addr.s_addr = inet_addr(add.c_str());
    if(connect(sock, (struct sockaddr *)&newSockAddr, sizeof(struct sockaddr)) != 0)
    {
    	stringstream sstream;
    	sstream << "Could not connect to " << hostname << " on port " << port;
    	throw SocketException ( sstream.str());
    }
}

int Socket::Receive(char *buff, int length)
{
    int bytes, total = 0;
    while(total != length)
    {
        bytes = recv(sock, buff+total, length-total,0);
        if ( bytes <= 0 )
        {
            throw SocketException ( "TCP: Could not read from socket." );
        }
        total += bytes;
    }
    return total;
}

int Socket::Send(const char *buff, int length)
{
    int bytes, total = 0;
    while(total != length)
    {
        bytes = send(sock,buff+total,length-total,0);
        if(bytes == -1)
        {
            throw SocketException ( "TCP: Could not write to socket." );
        }
        total += bytes;
    }
    return total;
}

void Socket::Close()
{
    if(sock > 0)
    {
        close(sock);
        sock = 0;
    }
	else
	{
        throw SocketException ( "TCP: Could not close socket." );
	}
}

const Socket& Socket::operator << ( const std::string& text)
{
    stringstream sstream;
    int length = text.length();
    if(!length)
    {
        string s = "0";
        Send(s.c_str(), 2);
        return *this;
    }
    sstream << length;
    string len = sstream.str();
    Send(len.c_str(), len.length()+1);
    Send(text.c_str(), text.length());
    return *this;
}

const Socket& Socket::operator >> ( std::string& text )
{
    text = "";
    string len;
    int length;
    stringstream sstream;
    char c;
    while(true)
    {
        if( Receive(&c,1) <= 0)
        {
            throw SocketException ( "TCP: Could not read from socket." );
        }
        if(c == '\0')
        {
            break;
        }
        len += c;
    }
    sstream << len;
    sstream >> length;
    if(!length)
    {
        return *this;
    }
    char *message = new char[length];
    Receive(message,length);
    text.append(message,length);
    if(message != NULL)
    {
        delete[] message;
        message = NULL;
    }
    return *this;
}