/** @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); setsockopt(sock, IPPROTO_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(); 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; 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; }