#ifndef __JNET__JTCPSOCKET__ #define __JNET__JTCPSOCKET__ #include "JLang/JException.hh" #include "JSystem/JNetwork.hh" #include "JNet/JSocket.hh" #include "JNet/JHostname.hh" #define IPROTO_TCP 6 #if !defined(TCP_KEEPIDLE) && defined(TCP_KEEPALIVE) #define TCP_KEEPIDLE TCP_KEEPALIVE #endif /** * \author mdejong */ namespace JNET {} namespace JPP { using namespace JNET; } namespace JNET { /** * TCP socket. */ class JTCPSocket : public JSocket { public: /** * Default constructor. */ JTCPSocket() : JSocket(AF_INET, SOCK_STREAM) {} /** * Constructor. * * \param server file descriptor of TCP server socket */ JTCPSocket(const int server) { accept(server); } /** * Set non-blocking of I/O. * * \param on true to enable non-blocking; false to disable */ void setNonBlocking(const bool on) { const int flags = fcntl(getFileDescriptor(), F_GETFL, -1); const int mask = FNDELAY; if (flags == -1) { THROW(JSocketException, "Get socket option failed " << errno); } if (((flags & mask) != mask && on) || ((flags & mask) != 0 && !on) ) { if (fcntl(getFileDescriptor(), F_SETFL, flags ^ mask) < 0) { THROW(JSocketException, "Set socket option failed " << errno); } } } /** * Get non-blocking of I/O. * * \return true if enabled non-blocking; else false */ bool getNonBlocking() const { const int flags = fcntl(getFileDescriptor(), F_GETFL, -1); const int mask = FNDELAY; if (flags == -1) { THROW(JSocketException, "Get socket option failed " << errno); } return ((flags & mask) != 0); } /** * Set the TCP idle time. * * \param t_s time [s] */ void setKeepIdle(const int t_s) { setOption(IPROTO_TCP, TCP_KEEPIDLE, t_s); } /** * Set the TCP idle count. * * \param count count */ void setKeepCnt(const int count) { setOption(IPROTO_TCP, TCP_KEEPCNT, count); } /** * Set the TCP interval time. * * \param t_s time [s] */ void setKeepIntvl(const int t_s) { setOption(IPROTO_TCP, TCP_KEEPINTVL, t_s); } /** * Set TCP no-delay. * * \param on true to set TCP no-delay; false to disable */ void setTcpNoDelay(const bool on) { setOption(IPPROTO_TCP, TCP_NODELAY, int(on ? 1 : 0)); } /** * Get TCP no-delay. * * \return true if TCP no-delay; else false */ bool getTcpNoDelay() const { return (getOption(IPPROTO_TCP, TCP_NODELAY) == 1); } /** * Accept connection from a server. * * \param server file descriptor of TCP server socket */ void accept(const int server) { socklen_t size = sizeof(sockaddr_in); fileDescriptor = ::accept(server, getSockaddr(), &size); } /** * Connect to port on local host. * * \param port port number */ void connect(const int port) { connect(INADDR_ANY, port); } /** * Connect to port on specified host. * * \param hostname host name */ void connect(const JHostname& hostname) { connect(hostname.hostname, hostname.port); } /** * Connect to port on specified host. * * \param hostname host name * \param port port number */ void connect(const std::string& hostname, const int port) { connect(JSYSTEM::getIPnumber(hostname), port); } /** * Connect to port on specified host. * * \param ip_number IP number * \param port port number */ void connect(const int ip_number, const int port) { setIPnumber(ip_number); setPort(port); if (::connect(getFileDescriptor(), getSockaddr(), sizeof(sockaddr_in)) < 0) { THROW(JSocketException, "Socket connection failed " << JSYSTEM::getIPaddress(ip_number) << ":" << port << " / " << getFileDescriptor() << " " << errno); } } }; } #endif