// Implementation of the Socket class. #include "Socket.h" #include "string.h" #include #include #include #include #include Socket::Socket() : m_sock ( -1 ) { memset ( &m_addr, 0, sizeof ( m_addr ) ); } Socket::~Socket() { if ( is_valid() ) ::close ( m_sock ); } bool Socket::create() { m_sock = socket ( AF_INET, SOCK_STREAM, 0); //IPPROTO_TCP if ( ! is_valid() ) return false; // TIME_WAIT - argh int on = 1; if ( setsockopt ( m_sock, SOL_SOCKET, SO_REUSEADDR, ( const char* ) &on, sizeof ( on ) ) == -1 ) return false; if (setsockopt(m_sock, SOL_TCP, TCP_NODELAY, (const char*) &on, sizeof(on)) <0) return false; return true; } bool Socket::shutdown() { int ret = 0; if ( is_valid() ) ret = ::shutdown ( m_sock, 2 ); m_sock=-1; if ( ret == 0 ) return true; return false; } bool Socket::bind ( const int port ) { if ( ! is_valid() ) return false; m_addr.sin_family = AF_INET; m_addr.sin_addr.s_addr = INADDR_ANY; m_addr.sin_port = htons ( port ); int bind_return = ::bind ( m_sock, ( struct sockaddr * ) &m_addr, sizeof ( m_addr ) ); if ( bind_return == -1 ) return false; return true; } bool Socket::listen() const { if ( ! is_valid() ) return false; int listen_return = ::listen ( m_sock, MAXCONNECTIONS ); if ( listen_return == -1 ) return false; return true; } bool Socket::accept ( Socket& new_socket ) const { int addr_length = sizeof ( m_addr ); new_socket.m_sock = ::accept ( m_sock, ( sockaddr * ) &m_addr, ( socklen_t * ) &addr_length ); if ( new_socket.m_sock <= 0 ) return false; return true; } bool Socket::send ( const std::string s ) const { int status = ::send ( m_sock, s.c_str(), s.size(), MSG_NOSIGNAL); if ( status == -1 ) return false; return true; } int Socket::recv ( std::string& s ) const { int sel; fd_set r; struct timeval timeout; if ( ! is_valid() ) return false; s=""; timeout.tv_sec = 0; // initialise le timeout, ici les secondes timeout.tv_usec = 1; // les microsecondes FD_ZERO(&r); // initialise la liste de fd FD_SET(m_sock, &r); // ajoute la socket dans la liste des fd sel = select(m_sock + 1, &r, NULL, NULL, &timeout); if (sel < 0) // select a rencontré un problème { return -1; } else if (sel == 0) // timeout { return 1; } else // quelque chose est à lire sur un file descriptor { if (FD_ISSET(m_sock, &r)) // si la socket est prête à être lue { char buf [ MAXRECV + 1 ]; s = ""; memset ( buf, 0, MAXRECV + 1 ); int status = ::recv ( m_sock, buf, MAXRECV, 0 ); if ( status == -1 ) { // là, nous ne sommes pas en présence d'une vraie erreur // car le mode non-bloquant est activé ici // (consulter la doc de la fct recv...) if (errno == EAGAIN ) { return 0; } return -1; } else if ( status == 0 ) { return 0; } else { s = buf; return status; } } } } bool Socket::connect ( const std::string host, const int port ) { if ( ! is_valid() ) return false; memset ( &m_addr, 0, sizeof ( m_addr ) ); m_addr.sin_family = AF_INET; m_addr.sin_port = htons ( port ); int status = inet_pton ( AF_INET, host.c_str(), &m_addr.sin_addr ); if ( errno == EAFNOSUPPORT ) return false; status = ::connect ( m_sock, ( sockaddr * ) &m_addr, sizeof ( m_addr ) ); if ( status == 0 ) return true; return false; } void Socket::set_non_blocking ( const bool b ) { int opts; opts = fcntl ( m_sock,F_GETFL ); if ( opts < 0 ) { return; } if ( b ) opts = ( opts | O_NONBLOCK ); else opts = ( opts & ~O_NONBLOCK ); fcntl ( m_sock, F_SETFL,opts ); }