From 6978f5362619b2936a27d85ff398bf96b6798790 Mon Sep 17 00:00:00 2001 From: kpl Date: Wed, 29 Jan 2020 11:42:41 -0500 Subject: [PATCH] cwTcpSocket.h/cpp,cwTcpSocketTest.cpp : Added socket::isConnected(),multicast_time_to_live(). --- cwTcpSocket.cpp | 34 ++++++++++++++++++++--- cwTcpSocket.h | 5 ++++ cwTcpSocketTest.cpp | 66 +++++++++++++++++++++------------------------ 3 files changed, 67 insertions(+), 38 deletions(-) diff --git a/cwTcpSocket.cpp b/cwTcpSocket.cpp index c459884..7e6319a 100644 --- a/cwTcpSocket.cpp +++ b/cwTcpSocket.cpp @@ -308,6 +308,19 @@ cw::rc_t cw::net::socket::destroy( handle_t& hRef ) return rc; } +cw::rc_t cw::net::socket::set_multicast_time_to_live( handle_t h, unsigned seconds ) +{ + rc_t rc = kOkRC; + socket_t* p = _handleToPtr(h); + + if( setsockopt( p->sockH, IPPROTO_IP, IP_MULTICAST_TTL, &seconds, sizeof(seconds) ) == cwSOCKET_SYS_ERR ) + { + rc = cwLogSysError(kOpFailRC,errno, "Attempt to set the socket multicast TTLfailed." ); + } + + return rc; +} + cw::rc_t cw::net::socket::join_multicast_group( handle_t h, const char* addrStr ) { rc_t rc = kOkRC; @@ -375,6 +388,8 @@ cw::rc_t cw::net::socket::accept( handle_t h ) p->fdH = fd; + p->flags = cwSetFlag(p->flags,kIsConnectedFl); + printf("Connect:%s\n",s); } @@ -389,6 +404,12 @@ cw::rc_t cw::net::socket::connect( handle_t h, const char* remoteAddr, portNumbe socket_t* p = _handleToPtr(h); return _connect(p,remoteAddr,remotePort); } + +bool cw::net::socket::isConnected( handle_t h ) +{ + socket_t* p = _handleToPtr(h); + return cwIsFlag(p->flags,kIsConnectedFl); +} cw::rc_t cw::net::socket::send( handle_t h, const void* data, unsigned dataByteCnt ) { @@ -398,7 +419,9 @@ cw::rc_t cw::net::socket::send( handle_t h, const void* data, unsigned dataByteC if( cwIsFlag(p->flags,kIsConnectedFl) == false ) return cwLogError(kInvalidOpRC,"socket::send() only works with connected sockets."); - if( ::send( p->sockH, data, dataByteCnt, 0 ) == cwSOCKET_SYS_ERR ) + int fd = p->fdH != cwSOCKET_NULL_SOCK ? p->fdH : p->sockH; + + if( ::send( fd, data, dataByteCnt, 0 ) == cwSOCKET_SYS_ERR ) return cwLogSysError(kOpFailRC,errno,"Send failed."); return kOkRC; @@ -434,7 +457,7 @@ cw::rc_t cw::net::socket::recieve( handle_t h, char* data, unsigned dataByteCnt, rc_t rc = kOkRC; ssize_t retVal = 0; socklen_t sizeOfRemoteAddr = fromAddr==NULL ? 0 : sizeof(struct sockaddr_in); - + errno = 0; if( recvByteCntRef != NULL ) @@ -444,7 +467,12 @@ cw::rc_t cw::net::socket::recieve( handle_t h, char* data, unsigned dataByteCnt, if((retVal = recvfrom(fd, data, dataByteCnt, 0, (struct sockaddr*)fromAddr, &sizeOfRemoteAddr )) == cwSOCKET_SYS_ERR ) return errno == EAGAIN ? kTimeOutRC : cwLogSysError(kOpFailRC,errno,"recvfrom() failed."); - + + + // if the read 0 bytes but did not time out this probably means that it was disconnected + if( retVal == 0 ) + p->flags = cwClrFlag(p->flags,kIsConnectedFl); + if( recvByteCntRef != NULL ) *recvByteCntRef = retVal; diff --git a/cwTcpSocket.h b/cwTcpSocket.h index 1fd6622..e0fc98b 100644 --- a/cwTcpSocket.h +++ b/cwTcpSocket.h @@ -42,6 +42,8 @@ namespace cw rc_t destroy( handle_t& hRef ); + rc_t set_multicast_time_to_live( handle_t h, unsigned seconds ); + rc_t join_multicast_group( handle_t h, const char* addr ); rc_t setTimeOutMs( handle_t h, unsigned timeOutMs ); @@ -53,6 +55,9 @@ namespace cw // the caller may use send() to communicate with the specified remote socket // without having to specify a destination address on each call. rc_t connect( handle_t h, const char* remoteAddr, portNumber_t port ); + + // Return true if this socket is connected to a remote endpoint. + bool isConnected( handle_t h ); // Send a message to a remote UDP socket over a previously connected socket rc_t send( handle_t h, const void* data, unsigned dataByteCnt ); diff --git a/cwTcpSocketTest.cpp b/cwTcpSocketTest.cpp index f5df924..1a0d59c 100644 --- a/cwTcpSocketTest.cpp +++ b/cwTcpSocketTest.cpp @@ -20,13 +20,13 @@ namespace cw { typedef struct app_str { + const char* remoteAddr; + unsigned remotePort; unsigned recvBufByteN; handle_t sockH; thread::handle_t threadH; unsigned cbN; bool serverFl; - bool readyFl; - bool connectedFl; } app_t; bool _dgramThreadFunc( void* arg ) @@ -61,44 +61,42 @@ namespace cw char buf[ app->recvBufByteN ]; unsigned recvBufByteN = 0; - if( !app->serverFl ) + if( isConnected(app->sockH) == false ) { - // the client node has nothing to do because it does not receive (it only sends) - sleepMs(50); - } - else - { - if( app->connectedFl == false ) + if( app->serverFl ) { if((rc = accept( app->sockH )) == kOkRC ) { - app->connectedFl = true; printf("Server connected.\n"); } } else - { - if((rc = recieve( app->sockH, buf, app->recvBufByteN, &recvBufByteN, nullptr )) == kOkRC ) + { + sleepMs(50); + } + } + else + { + if((rc = recieve( app->sockH, buf, app->recvBufByteN, &recvBufByteN, nullptr )) == kOkRC ) + { + // if the server disconnects then recvBufByteN + if( !isConnected( app->sockH) ) { - // if the server disconnects then recvBufByteN - if( recvBufByteN==0 ) - { - app->connectedFl = false; - } - else - { - printf("%i %s\n", recvBufByteN, buf ); - } + printf("Disconnected."); + } + else + { + printf("%i %s\n", recvBufByteN, buf ); } } - } + } // count the number of callbacks app->cbN += 1; if( app->cbN % 10 == 0) { // print '+' when the server is not connected. - printf("%s", app->serverFl && app->connectedFl == false ? "+" : "."); + printf("%s", isConnected(app->sockH) == false ? "+" : "."); fflush(stdout); } @@ -160,12 +158,12 @@ cw::rc_t cw::net::socket::test_tcp( portNumber_t localPort, const char* remoteAd bool streamFl = !dgramFl; bool clientFl = !serverFl; unsigned flags = kTcpFl | kBlockingFl; - + + app.remoteAddr = remoteAddr; + app.remotePort = remotePort; app.cbN = 0; app.recvBufByteN = sbufN+1; app.serverFl = serverFl; - app.readyFl = false; - app.connectedFl = false; if( serverFl && streamFl ) flags |= kListenFl; @@ -181,13 +179,12 @@ cw::rc_t cw::net::socket::test_tcp( portNumber_t localPort, const char* remoteAd if((rc = thread::create( app.threadH, streamFl ? _tcpStreamThreadFunc : _dgramThreadFunc, &app )) != kOkRC ) goto errLabel; - // if this is the client then connect to the server (which must have already been started) + // if this is a streaming client then connect to the server (which must have already been started) if( streamFl && clientFl ) { + // note that this creates a bi-directional stream if((rc = connect(app.sockH,remoteAddr,remotePort)) != kOkRC ) - goto errLabel; - - app.connectedFl = true; + goto errLabel; } printf("Starting node ....\n"); @@ -205,16 +202,15 @@ cw::rc_t cw::net::socket::test_tcp( portNumber_t localPort, const char* remoteAd if( strcmp(sbuf,"quit\n") == 0) break; - // when using streams only the client can send - if( streamFl & clientFl ) + if( streamFl ) { + // when using streams no remote address is necessary printf("Sending:%s",sbuf); send(app.sockH, sbuf, strlen(sbuf)+1 ); } - - // when using dgrams the dest. address is need to send - if( dgramFl ) + else { + // when using dgrams the dest. address is required printf("Sending:%s",sbuf); send(app.sockH, sbuf, strlen(sbuf)+1, remoteAddr, remotePort); }