cwTcpSocket.h/cpp,cwTcpSocketTest.cpp : Added socket::isConnected(),multicast_time_to_live().

This commit is contained in:
kpl 2020-01-29 11:42:41 -05:00
parent 39fdb41329
commit 6978f53626
3 changed files with 67 additions and 38 deletions

View File

@ -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;

View File

@ -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 );

View File

@ -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);
}