Changeset 5 in libcf++


Ignore:
Timestamp:
03/21/15 19:54:07 (10 years ago)
Author:
cheese
Message:

#1 get address from local socket or peer socket

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/cf/network.h

    r4 r5  
    2020    {
    2121        /**
     22         * network host
     23         */
     24        class host
     25        {
     26        private:
     27            std::string mAddress;
     28            cf::uint16_t mPort;
     29
     30        public:
     31            /**
     32             * constructor
     33             * @param address host address
     34             * @param port port number
     35             */
     36            host(const std::string & address = "",
     37                 const cf::uint16_t port = 0);
     38
     39            /**
     40             * get host address
     41             * @return host address
     42             */
     43            std::string address() const;
     44
     45            /**
     46             * get port number
     47             * @return port number
     48             */
     49            cf::uint16_t port() const;
     50
     51            /**
     52             * is empty ?
     53             * @return true; false
     54             */
     55            cf::bool_t empty() const;
     56        };
     57
     58        /**
    2259         * TCP Socket
    2360         */
     
    2764            cf::socket_t mSocket;
    2865            cf::int32_t mTimeout;
    29             std::string mHost;
    30             cf::uint16_t mPort;
    3166
    3267            /**
     
    3570             * @throw cf::exception
    3671             */
    37             cf::void_t receive(bin & out)
     72            cf::void_t receive(bin & out) const
    3873                throw (cf::exception);
    3974
     
    5893
    5994            /**
    60              * connect to host:port
    61              * @param host host
    62              * @param port port
     95             * connect to address:port
     96             * @param peer peer host
    6397             * @param timeout timeout
    6498             * @throw cf::exception
    6599             */
    66             cf::void_t connect(const cf::char_t * host,
    67                                const cf::uint16_t port,
     100            cf::void_t connect(const host & peer,
    68101                               const cf::int32_t timeout = 0)
    69102                throw (cf::exception);
     
    76109             */
    77110            cf::void_t listen(const cf::uint16_t port,
    78                               const cf::int32_t backlog = 5)
     111                              const cf::int32_t backlog = 5) const
    79112                throw (cf::exception);
    80113
     
    84117             * @throw cf::exception
    85118             */
    86             tcp accept()
     119            tcp accept() const
    87120                throw (cf::exception);
    88121
     
    108141             * @throw cf::exception
    109142             */
    110             cf::void_t send(const bin & in)
     143            cf::void_t send(const bin & in) const
    111144                throw (cf::exception);
    112145
     
    117150             * @throw cf::exception
    118151             */
    119             bin receive(const cf::int32_t size)
     152            bin receive(const cf::int32_t size) const
    120153                throw (cf::exception);
    121154
     
    125158             * @throw cf::exception
    126159             */
    127             bin receive()
     160            bin receive() const
    128161                throw (cf::exception);
    129162
     
    133166            cf::void_t getOption(const cf::int32_t optname,
    134167                                 cf::void_t * optval,
    135                                  cf::int32_t * optlen)
     168                                 cf::int32_t * optlen) const
    136169                throw (cf::exception);
    137170
     
    141174            cf::void_t setOption(const cf::int32_t optname,
    142175                                 const cf::void_t * optval,
    143                                  const cf::int32_t optlen)
    144                 throw (cf::exception);
    145 
    146             /**
    147              * set non-blocking
    148              * @param flag true; false
    149              * @see setTimeout
    150              */
    151             cf::void_t setNonBlocking(const cf::bool_t flag);
     176                                 const cf::int32_t optlen) const
     177                throw (cf::exception);
    152178
    153179            /**
     
    157183             */
    158184            cf::void_t setTimeout(const cf::int32_t seconds);
     185
     186            /**
     187             * get local host
     188             * @return local host
     189             * @see cf::network::host
     190             */
     191            host local() const
     192                throw (cf::exception);
     193
     194            /**
     195             * get peer host
     196             * @return peer host
     197             * @see cf::network::host
     198             */
     199            host peer() const
     200                throw (cf::exception);
    159201        };
    160202
  • trunk/src/network.cpp

    r4 r5  
    3737#endif
    3838
    39 #define ALLOW_SOCKET_TIME_WAIT
    40 
    41 cf::socket_t gInvalidSocket = -1;
     39#define INVALID_SOCKET  -1
    4240
    4341/*--------------------------------------------------------------*/
     
    4846long GetMACAddress(cf::char_t *addr);
    4947
     48static std::string convertAddressToString(struct sockaddr_in & addr)
     49{
     50    cf::uint8_t * bytes = NULL;
     51    cf::char_t str[32] = {0x00};
     52
     53    bytes = reinterpret_cast<cf::uint8_t *>(&addr.sin_addr.s_addr);
     54    snprintf(str, sizeof(str) - 1, "%u.%u.%u.%u", bytes[0],
     55                                                  bytes[1],
     56                                                  bytes[2],
     57                                                  bytes[3]);
     58
     59    return str;
     60}
     61
     62static cf::void_t setNonBlocking(const cf::socket_t sock,
     63                                 const cf::bool_t flag)
     64{
     65#ifdef _ON_WINDOWS
     66    cf::ulong_t mode = flag ? 1 : 0;
     67    ioctlsocket(sock, FIONBIO, &mode);
     68#else
     69    cf::int32_t mode = fcntl(sock, F_GETFL, 0);
     70
     71    if (flag)   mode |=  O_NONBLOCK;
     72    else        mode &= ~O_NONBLOCK;
     73
     74    fcntl(sock, F_SETFL, mode);
     75#endif
     76}
     77
    5078static cf::void_t waitForTimeout(const cf::socket_t sock,
    5179                                 const cf::int32_t timeout,
     
    87115}
    88116
    89 static cf::void_t setLinger(cf::network::tcp & tcp)
    90     throw (cf::exception)
    91 {
    92 #ifdef ALLOW_SOCKET_TIME_WAIT
    93     return;
    94 #else
     117static cf::void_t setReuseAddress(const cf::network::tcp & tcp)
     118    throw (cf::exception)
     119{
    95120    try
    96121    {
    97         struct linger linger;
    98 
    99         linger.l_onoff = 1;
    100         linger.l_linger = 0;
    101 
    102         tcp.setOption(SO_LINGER, &linger, sizeof(linger));
     122        cf::int32_t reuseaddr = 1;
     123
     124        tcp.setOption(SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
    103125    }
    104126    catch (cf::exception & e)
     
    106128        FORWARD_EXCEPTION(e);
    107129    }
    108 #endif
    109 }
    110 
    111 static cf::void_t setReuseAddress(cf::network::tcp & tcp)
    112     throw (cf::exception)
    113 {
    114     try
    115     {
    116         cf::int32_t reuseaddr = 1;
    117 
    118         tcp.setOption(SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
    119     }
    120     catch (cf::exception & e)
    121     {
    122         FORWARD_EXCEPTION(e);
    123     }
     130}
     131
     132typedef cf::int32_t (*getSocketNameAPI)(cf::socket_t sock,
     133                                        struct sockaddr * addr,
     134                                        socklen_t *len);
     135
     136static cf::network::host getSocketNameFromFunction(const cf::socket_t sock,
     137                                                   getSocketNameAPI api)
     138    throw (cf::exception)
     139{
     140    cf::int32_t result = 0;
     141    struct sockaddr_in addr;
     142    socklen_t len = sizeof(struct sockaddr_in);
     143
     144    result = api(sock, (struct sockaddr *)&addr, &len);
     145    if (result < 0)
     146        THROW_EXCEPTION("cannot get sockket or peer name ("
     147                        << cf::exception::systemCode()
     148                        << ")");
     149
     150    return cf::network::host(convertAddressToString(addr), addr.sin_port);
    124151}
    125152/*--------------------------------------------------------------*/
     153
     154cf::network::host::host(const std::string & address,
     155                        const cf::uint16_t port)
     156    : mAddress(address),
     157      mPort(port)
     158{
     159}
     160
     161std::string cf::network::host::address() const
     162{
     163    return mAddress;
     164}
     165
     166cf::uint16_t cf::network::host::port() const
     167{
     168    return mPort;
     169}
     170
     171cf::bool_t cf::network::host::empty() const
     172{
     173    return (address().empty() || port() <= 0) ? true : false;
     174}
    126175
    127176cf::network::tcp::tcp(const cf::socket_t attachedSocket)
     
    145194    }
    146195
    147     if (mSocket == gInvalidSocket)
     196    if (mSocket == INVALID_SOCKET)
    148197        mSocket = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    149198
     
    159208cf::void_t cf::network::tcp::close()
    160209{
    161     if (mSocket == gInvalidSocket)
     210    if (mSocket == INVALID_SOCKET)
    162211        return;
    163212
    164213    closesocket(mSocket);
    165214
    166     mSocket = gInvalidSocket;
    167     mHost = "";
    168     mPort = 0;
    169 }
    170 
    171 cf::void_t cf::network::tcp::connect(const cf::char_t * host,
    172                                      const cf::uint16_t port,
     215    mSocket = INVALID_SOCKET;
     216}
     217
     218cf::void_t cf::network::tcp::connect(const cf::network::host & peer,
    173219                                     const cf::int32_t timeout)
    174220    throw (cf::exception)
    175221{
    176     if (!host || !port)
     222    if (peer.empty())
    177223        THROW_EXCEPTION("invalid host info");
    178224
     
    183229    struct hostent * hostEnt;
    184230
     231    const cf::char_t * host = peer.address().c_str();
     232    cf::uint16_t port = peer.port();
     233
    185234    /* 1. set data */
    186235    addr.sin_family         = AF_INET;
     
    204253    try
    205254    {
    206         setLinger(*this);
    207255        setReuseAddress(*this);
    208256    }
     
    212260    }
    213261
    214     if (timeout > 0)
    215         setNonBlocking(true);
     262    setTimeout(timeout);
    216263
    217264    /* 4. connect */
     
    243290        }
    244291    }
    245 
    246     /* set */
    247     mHost = host;
    248     mPort = port;
    249     mTimeout = timeout;
    250292}
    251293
    252294cf::void_t cf::network::tcp::listen(const cf::uint16_t port,
    253                                     const cf::int32_t backlog)
     295                                    const cf::int32_t backlog) const
    254296    throw (cf::exception)
    255297{
     
    268310    try
    269311    {
    270         setLinger(*this);
    271312        setReuseAddress(*this);
    272313    }
     
    285326}
    286327
    287 cf::network::tcp cf::network::tcp::accept()
     328cf::network::tcp cf::network::tcp::accept() const
    288329    throw (cf::exception)
    289330{
     
    302343    throw (exception)
    303344{
    304     if (sock == gInvalidSocket)
     345    if (sock == INVALID_SOCKET)
    305346        THROW_EXCEPTION("has invalid socket");
    306347
     
    313354    throw (exception)
    314355{
    315     if (mSocket == gInvalidSocket)
     356    if (mSocket == INVALID_SOCKET)
    316357        THROW_EXCEPTION("has invalid socket");
    317358
    318359    cf::socket_t sock = mSocket;
    319360
    320     mSocket = gInvalidSocket;
     361    mSocket = INVALID_SOCKET;
    321362
    322363    return sock;
    323364}
    324365
    325 cf::void_t cf::network::tcp::send(const cf::bin & in)
     366cf::void_t cf::network::tcp::send(const cf::bin & in) const
    326367    throw (cf::exception)
    327368{
     
    337378}
    338379
    339 cf::void_t cf::network::tcp::receive(cf::bin & out)
     380cf::void_t cf::network::tcp::receive(cf::bin & out) const
    340381    throw (cf::exception)
    341382{
     
    364405}
    365406
    366 cf::bin cf::network::tcp::receive(const cf::int32_t size)
     407cf::bin cf::network::tcp::receive(const cf::int32_t size) const
    367408    throw (cf::exception)
    368409{
     
    375416}
    376417
    377 cf::bin cf::network::tcp::receive()
     418cf::bin cf::network::tcp::receive() const
    378419    throw (cf::exception)
    379420{
     
    396437cf::void_t cf::network::tcp::getOption(const cf::int32_t optname,
    397438                                       cf::void_t * optval,
    398                                        cf::int32_t * optlen)
     439                                       cf::int32_t * optlen) const
    399440    throw (cf::exception)
    400441{
     
    416457cf::void_t cf::network::tcp::setOption(const cf::int32_t optname,
    417458                                       const cf::void_t * optval,
    418                                        const cf::int32_t optlen)
     459                                       const cf::int32_t optlen) const
    419460    throw (cf::exception)
    420461{
     
    434475}
    435476
    436 cf::void_t cf::network::tcp::setNonBlocking(const cf::bool_t flag)
    437 {
    438 #ifdef _ON_WINDOWS
    439     cf::ulong_t mode = flag ? 1 : 0;
    440     ioctlsocket(mSocket, FIONBIO, &mode);
    441 #else
    442     cf::int32_t mode = fcntl(mSocket, F_GETFL, 0);
    443 
    444     if (flag)   mode |=  O_NONBLOCK;
    445     else        mode &= ~O_NONBLOCK;
    446 
    447     fcntl(mSocket, F_SETFL, mode);
    448 #endif
    449 }
    450 
    451477cf::void_t cf::network::tcp::setTimeout(const cf::int32_t seconds)
    452478{
     479    setNonBlocking(mSocket, seconds > 0 /*? true : false*/);
    453480    mTimeout = seconds;
     481}
     482
     483cf::network::host cf::network::tcp::peer() const
     484    throw (cf::exception)
     485{
     486    try
     487    {
     488        return getSocketNameFromFunction(mSocket, getpeername);
     489    }
     490    catch (cf::exception & e)
     491    {
     492        FORWARD_EXCEPTION(e);
     493    }
     494}
     495
     496cf::network::host cf::network::tcp::local() const
     497    throw (cf::exception)
     498{
     499    try
     500    {
     501        return getSocketNameFromFunction(mSocket, getsockname);
     502    }
     503    catch (cf::exception & e)
     504    {
     505        FORWARD_EXCEPTION(e);
     506    }
    454507}
    455508
  • trunk/test/test.cpp

    r4 r5  
    213213        {
    214214            client.attach(server.accept().detach());
     215            cf::network::host peer = client.peer();
     216            std::cout << "client <"
     217                      << peer.address() << ":" << peer.port()
     218                      << "> is connected"
     219                      << std::endl;
    215220            msg = client.receive();
    216221            client.send(msg);
     
    237242    {
    238243        cf::network::tcp client;
     244        cf::network::host host(HOST, PORT);
     245
    239246        cf::ulong_t tid = cf::task::thread::id();
    240247        cf::bin msg(STR(STRING << " " << tid).c_str());
    241248        cf::bin response;
    242249
    243         client.connect(HOST, PORT, TIMEOUT);
     250        client.connect(host, TIMEOUT);
    244251        client.send(msg);
    245252        response = client.receive();
Note: See TracChangeset for help on using the changeset viewer.