Blame view

src/Socket.cpp 4.33 KB
Imanol-Mikel Barba Sabariego authored
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/** @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"

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);
Imanol-Mikel Barba Sabariego authored
30
    setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof optval);
Imanol-Mikel Barba Sabariego authored
31
32
33
34
35
36
37
}

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());
Imanol-Mikel Barba Sabariego authored
38
    if(::bind(sock, (struct sockaddr *)&sockAddr, sizeof(struct sockaddr)) != 0)
Imanol-Mikel Barba Sabariego authored
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
    {
    	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." );
	}
}
Imanol-Mikel Barba Sabariego authored
135
const Socket& Socket::operator << ( const std::string& text)
Imanol-Mikel Barba Sabariego authored
136
{
Imanol-Mikel Barba Sabariego authored
137
    stringstream sstream;
Imanol-Mikel Barba Sabariego authored
138
139
140
    int length = text.length();
    if(!length)
    {
Imanol-Mikel Barba Sabariego authored
141
        string s = "0";
Imanol-Mikel Barba Sabariego authored
142
143
144
        Send(s.c_str(), 2);
        return *this;
    }
Imanol-Mikel Barba Sabariego authored
145
146
147
148
149
150
151
    sstream << length;
    string len = sstream.str();
    char* msg = new char[len.length() + text.length() + 1];
    strcpy(msg,len.c_str());
    strcpy(msg+len.length()+1,text.c_str()); 
    Send(msg, text.length() + len.length() + 1);
    delete[] msg;
Imanol-Mikel Barba Sabariego authored
152
153
154
    return *this;
}
Imanol-Mikel Barba Sabariego authored
155
const Socket& Socket::operator >> ( std::string& text )
Imanol-Mikel Barba Sabariego authored
156
157
{
    text = "";
Imanol-Mikel Barba Sabariego authored
158
159
160
    string len;
    int length;
    stringstream sstream;
Imanol-Mikel Barba Sabariego authored
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
    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;
Imanol-Mikel Barba Sabariego authored
176
177
178
179
    if(!length)
    {
        return *this;
    }
Imanol-Mikel Barba Sabariego authored
180
181
182
183
184
185
186
187
    char *message = new char[length];
    Receive(message,length);
    text.append(message,length);
    if(message != NULL)
    {
        delete[] message;
        message = NULL;
    }
Imanol-Mikel Barba Sabariego authored
188
    return *this;
Imanol-Mikel Barba Sabariego authored
189
}