cwTcpSocket*.h/cpp : Updated to support more socket options and configurations.
This commit is contained in:
parent
c37595578a
commit
6590d4b181
279
cwTcpSocket.cpp
279
cwTcpSocket.cpp
@ -34,6 +34,7 @@ namespace cw
|
||||
typedef struct socket_str
|
||||
{
|
||||
int sockH;
|
||||
int fdH;
|
||||
unsigned flags;
|
||||
unsigned recvBufByteCnt;
|
||||
struct sockaddr_in sockaddr;
|
||||
@ -45,6 +46,18 @@ namespace cw
|
||||
|
||||
rc_t _destroy( socket_t* p )
|
||||
{
|
||||
|
||||
// close the fdH
|
||||
if( p->fdH != cwSOCKET_NULL_SOCK )
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
if( ::close(p->fdH) != 0 )
|
||||
cwLogSysError(kOpFailRC,errno,"The socket fd close failed." );
|
||||
|
||||
p->fdH = cwSOCKET_NULL_SOCK;
|
||||
}
|
||||
|
||||
// close the socket
|
||||
if( p->sockH != cwSOCKET_NULL_SOCK )
|
||||
{
|
||||
@ -52,7 +65,7 @@ namespace cw
|
||||
|
||||
if( ::close(p->sockH) != 0 )
|
||||
cwLogSysError(kOpFailRC,errno,"The socket close failed." );
|
||||
|
||||
|
||||
p->sockH = cwSOCKET_NULL_SOCK;
|
||||
}
|
||||
|
||||
@ -65,8 +78,8 @@ namespace cw
|
||||
{
|
||||
memset(retAddrPtr,0,sizeof(struct sockaddr_in));
|
||||
|
||||
if( portNumber == kInvalidPortNumber )
|
||||
return cwLogError(kInvalidArgRC,"The port number %i cannot be used.",kInvalidPortNumber);
|
||||
//if( portNumber == kInvalidPortNumber )
|
||||
// return cwLogError(kInvalidArgRC,"The port number %i cannot be used.",kInvalidPortNumber);
|
||||
|
||||
if( addrStr == NULL )
|
||||
retAddrPtr->sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
@ -80,7 +93,8 @@ namespace cw
|
||||
|
||||
//retAddrPtr->sin_len = sizeof(struct sockaddr_in);
|
||||
retAddrPtr->sin_family = AF_INET;
|
||||
retAddrPtr->sin_port = htons(portNumber);
|
||||
if( portNumber != kInvalidPortNumber )
|
||||
retAddrPtr->sin_port = htons(portNumber);
|
||||
|
||||
return kOkRC;
|
||||
}
|
||||
@ -104,7 +118,27 @@ namespace cw
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
rc_t _setTimeOutMs( socket_t* p, unsigned timeOutMs )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
|
||||
struct timeval timeOut;
|
||||
|
||||
// set the socket time out
|
||||
timeOut.tv_sec = timeOutMs/1000;
|
||||
timeOut.tv_usec = (timeOutMs - (timeOut.tv_sec * 1000)) * 1000;
|
||||
|
||||
if( setsockopt( p->sockH, SOL_SOCKET, SO_RCVTIMEO, &timeOut, sizeof(timeOut) ) == cwSOCKET_SYS_ERR )
|
||||
{
|
||||
rc = cwLogSysError(kOpFailRC,errno, "Attempt to set the socket timeout failed." );
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
errLabel:
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -124,43 +158,25 @@ cw::rc_t cw::net::socket::create(
|
||||
|
||||
socket_t* p = mem::allocZ<socket_t>();
|
||||
p->sockH = cwSOCKET_NULL_SOCK;
|
||||
p->fdH = cwSOCKET_NULL_SOCK;
|
||||
|
||||
int type = cwIsFlag(flags,kStreamFl) ? SOCK_STREAM : SOCK_DGRAM;
|
||||
int protocol = cwIsFlag(flags,kTcpFl) ? 0 : IPPROTO_UDP;
|
||||
|
||||
// get a handle to the socket
|
||||
if(( p->sockH = ::socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == cwSOCKET_SYS_ERR )
|
||||
if(( p->sockH = ::socket( AF_INET, type, protocol ) ) == cwSOCKET_SYS_ERR )
|
||||
return cwLogSysError(kOpFailRC, errno, "Socket create failed." );
|
||||
|
||||
// create the local address
|
||||
if((rc = _initAddr(p, NULL, port, &p->sockaddr )) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
// bind the socket to a local address/port
|
||||
if( (bind( p->sockH, (struct sockaddr*)&p->sockaddr, sizeof(p->sockaddr))) == cwSOCKET_SYS_ERR )
|
||||
{
|
||||
rc = cwLogSysError(kOpFailRC,errno,"Socket bind failed." );
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// if a remote addr was given connect this socket to it
|
||||
if( remoteAddr != NULL )
|
||||
if((rc = _connect(p,remoteAddr,remotePort)) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
// if this socket should block
|
||||
if( cwIsFlag(flags,kBlockingFl) )
|
||||
if( cwIsFlag(flags,kBlockingFl))
|
||||
{
|
||||
struct timeval timeOut;
|
||||
|
||||
// set the socket time out
|
||||
timeOut.tv_sec = timeOutMs/1000;
|
||||
timeOut.tv_usec = (timeOutMs - (timeOut.tv_sec * 1000)) * 1000;
|
||||
|
||||
if( setsockopt( p->sockH, SOL_SOCKET, SO_RCVTIMEO, &timeOut, sizeof(timeOut) ) == cwSOCKET_SYS_ERR )
|
||||
if( timeOutMs > 0 )
|
||||
{
|
||||
rc = cwLogSysError(kOpFailRC,errno, "Attempt to set the socket timeout failed." );
|
||||
goto errLabel;
|
||||
_setTimeOutMs(p,timeOutMs);
|
||||
}
|
||||
|
||||
|
||||
p->flags = cwSetFlag(p->flags,kIsBlockingFl);
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
@ -184,18 +200,90 @@ cw::rc_t cw::net::socket::create(
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( cwIsFlag(flags,kReuseAddrFl) )
|
||||
{
|
||||
unsigned int reuseaddr = 1;
|
||||
if( setsockopt(p->sockH, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuseaddr, sizeof(reuseaddr)) == cwSOCKET_SYS_ERR )
|
||||
{
|
||||
rc = cwLogSysError(kOpFailRC,errno, "Attempt to set the socket 'reuse address' attribute failed." );
|
||||
goto errLabel;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SO_REUSEPORT
|
||||
if( cwIsFlag(flags,kReusePortFl) )
|
||||
{
|
||||
unsigned int reuseaddr = 1;
|
||||
if(setsockopt(p->sockH, SOL_SOCKET, SO_REUSEPORT, (const char*)&reuseaddr, sizeof(reuseaddr)) == cwSOCKET_SYS_ERR )
|
||||
{
|
||||
rc = cwLogSysError(kOpFailRC,errno, "Attempt to set the socket 'reuse port' attribute failed." );
|
||||
goto errLabel;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if( cwIsFlag(flags,kMultiCastTtlFl) )
|
||||
{
|
||||
unsigned char ttl = 1;
|
||||
if( setsockopt(p->sockH, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl, sizeof(ttl)) == cwSOCKET_SYS_ERR )
|
||||
{
|
||||
rc = cwLogSysError(kOpFailRC,errno, "Attempt to set the socket 'multicast TTL' attribute failed." );
|
||||
goto errLabel;
|
||||
}
|
||||
}
|
||||
|
||||
if( cwIsFlag(flags,kMultiCastLoopFl) )
|
||||
{
|
||||
|
||||
unsigned char loopback = 1;
|
||||
if( setsockopt(p->sockH, IPPROTO_IP, IP_MULTICAST_LOOP, (const char*)&loopback, sizeof(loopback)) == cwSOCKET_SYS_ERR )
|
||||
{
|
||||
rc = cwLogSysError(kOpFailRC,errno, "Attempt to set the socket 'reuse port' attribute failed." );
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// if broadcast option was requested.
|
||||
if( cwIsFlag(flags,kBroadcastFl) )
|
||||
{
|
||||
int bcastFl = 1;
|
||||
int bcastFl = 1;
|
||||
if( setsockopt( p->sockH, SOL_SOCKET, SO_BROADCAST, &bcastFl, sizeof(bcastFl) ) == cwSOCKET_SYS_ERR )
|
||||
{
|
||||
rc = cwLogSysError(kOpFailRC,errno, "Attempt to set the socket broadcast attribute failed." );
|
||||
goto errLabel;
|
||||
}
|
||||
}
|
||||
|
||||
// create the local address
|
||||
if((rc = _initAddr(p, NULL, port, &p->sockaddr )) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
|
||||
// bind the socket to a local address/port
|
||||
if( (bind( p->sockH, (struct sockaddr*)&p->sockaddr, sizeof(p->sockaddr))) == cwSOCKET_SYS_ERR )
|
||||
{
|
||||
rc = cwLogSysError(kOpFailRC,errno,"Socket bind failed." );
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// if a remote addr was given connect this socket to it
|
||||
if( remoteAddr != NULL )
|
||||
if((rc = _connect(p,remoteAddr,remotePort)) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
// if the socket should be marked for listening
|
||||
if( cwIsFlag(flags,kListenFl) )
|
||||
{
|
||||
if( ::listen(p->sockH, 10) != 0 )
|
||||
{
|
||||
rc = cwLogSysError(kOpFailRC,errno,"Socket listen() failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
}
|
||||
|
||||
errLabel:
|
||||
if(rc != kOkRC )
|
||||
_destroy(p);
|
||||
@ -204,7 +292,7 @@ cw::rc_t cw::net::socket::create(
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
cw::rc_t cw::net::socket::destroy( handle_t& hRef )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
@ -220,6 +308,82 @@ cw::rc_t cw::net::socket::destroy( handle_t& hRef )
|
||||
return rc;
|
||||
}
|
||||
|
||||
cw::rc_t cw::net::socket::join_multicast_group( handle_t h, const char* addrStr )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
socket_t* p = _handleToPtr(h);
|
||||
struct ip_mreq req;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
|
||||
if(inet_pton(AF_INET,addrStr,&req.imr_multiaddr.s_addr) == 0 )
|
||||
{
|
||||
rc = cwLogSysError(kOpFailRC,errno, "The network address string '%s' could not be converted to a netword address structure.",cwStringNullGuard(addrStr) );
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
req.imr_interface.s_addr = INADDR_ANY;
|
||||
|
||||
if(setsockopt(p->sockH, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&req, sizeof(req)) == cwSOCKET_SYS_ERR )
|
||||
{
|
||||
rc = cwLogSysError(kOpFailRC,errno, "Attempt to add socket to multicast group on '%s' failed.", cwStringNullGuard(addrStr) );
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
errLabel:
|
||||
return rc;
|
||||
}
|
||||
|
||||
cw::rc_t cw::net::socket::setTimeOutMs( handle_t h, unsigned timeOutMs )
|
||||
{
|
||||
socket_t* p = _handleToPtr(h);
|
||||
return _setTimeOutMs(p,timeOutMs);
|
||||
}
|
||||
|
||||
|
||||
cw::rc_t cw::net::socket::accept( handle_t h )
|
||||
{
|
||||
struct sockaddr_storage remoteAddr; // connector's address information
|
||||
socklen_t sin_size = sizeof(remoteAddr);
|
||||
|
||||
rc_t rc = kOkRC;
|
||||
int fd = cwSOCKET_NULL_SOCK;
|
||||
|
||||
socket_t* p = _handleToPtr(h);
|
||||
|
||||
if((fd = accept(p->sockH, (struct sockaddr*)&remoteAddr, &sin_size)) < 0)
|
||||
{
|
||||
if( errno == EAGAIN || errno == EWOULDBLOCK )
|
||||
rc = kTimeOutRC;
|
||||
else
|
||||
{
|
||||
rc = cwLogSysError(kOpFailRC,errno,"Socket accept() failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char s[INET_ADDRSTRLEN+1];
|
||||
|
||||
addrToString( (struct sockaddr_in*)&remoteAddr, s, INET_ADDRSTRLEN );
|
||||
|
||||
if( p->fdH != cwSOCKET_NULL_SOCK )
|
||||
{
|
||||
close(p->fdH);
|
||||
p->fdH = cwSOCKET_NULL_SOCK;
|
||||
}
|
||||
|
||||
p->fdH = fd;
|
||||
|
||||
printf("Connect:%s\n",s);
|
||||
|
||||
}
|
||||
|
||||
errLabel:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
cw::rc_t cw::net::socket::connect( handle_t h, const char* remoteAddr, portNumber_t remotePort )
|
||||
{
|
||||
socket_t* p = _handleToPtr(h);
|
||||
@ -232,7 +396,7 @@ cw::rc_t cw::net::socket::send( handle_t h, const void* data, unsigned dataByteC
|
||||
errno = 0;
|
||||
|
||||
if( cwIsFlag(p->flags,kIsConnectedFl) == false )
|
||||
return cwLogError(kInvalidOpRC,"cmUdpSend() only works with connected sockets.");
|
||||
return cwLogError(kInvalidOpRC,"socket::send() only works with connected sockets.");
|
||||
|
||||
if( ::send( p->sockH, data, dataByteCnt, 0 ) == cwSOCKET_SYS_ERR )
|
||||
return cwLogSysError(kOpFailRC,errno,"Send failed.");
|
||||
@ -246,7 +410,7 @@ cw::rc_t cw::net::socket::send( handle_t h, const void* data, unsigned dataByteC
|
||||
|
||||
errno = 0;
|
||||
|
||||
if( sendto(p->sockH, data, dataByteCnt, 0, (struct sockaddr*)remoteAddr, sizeof(*remoteAddr)) == cwSOCKET_SYS_ERR )
|
||||
if( ::sendto(p->sockH, data, dataByteCnt, 0, (struct sockaddr*)remoteAddr, sizeof(*remoteAddr)) == cwSOCKET_SYS_ERR )
|
||||
return cwLogSysError(kOpFailRC,errno,"Send to remote addr. failed.");
|
||||
|
||||
return kOkRC;
|
||||
@ -276,7 +440,9 @@ cw::rc_t cw::net::socket::recieve( handle_t h, char* data, unsigned dataByteCnt,
|
||||
if( recvByteCntRef != NULL )
|
||||
*recvByteCntRef = 0;
|
||||
|
||||
if((retVal = recvfrom(p->sockH, data, dataByteCnt, 0, (struct sockaddr*)fromAddr, &sizeOfRemoteAddr )) == cwSOCKET_SYS_ERR )
|
||||
int fd = p->fdH != cwSOCKET_NULL_SOCK ? p->fdH : p->sockH;
|
||||
|
||||
if((retVal = recvfrom(fd, data, dataByteCnt, 0, (struct sockaddr*)fromAddr, &sizeOfRemoteAddr )) == cwSOCKET_SYS_ERR )
|
||||
return errno == EAGAIN ? kTimeOutRC : cwLogSysError(kOpFailRC,errno,"recvfrom() failed.");
|
||||
|
||||
if( recvByteCntRef != NULL )
|
||||
@ -344,6 +510,43 @@ cw::rc_t cw::net::socket::select_recieve(handle_t h, char* buf, unsigned bufByte
|
||||
return rc;
|
||||
}
|
||||
|
||||
cw::rc_t cw::net::socket::recv_from(handle_t h, char* buf, unsigned bufByteCnt, unsigned* recvByteCntRef, struct sockaddr_in* fromAddr )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
socket_t* p = _handleToPtr(h);
|
||||
socklen_t addrlen = 0;
|
||||
int bytesN = 0;
|
||||
|
||||
if( recvByteCntRef != nullptr )
|
||||
*recvByteCntRef = 0;
|
||||
|
||||
if( fromAddr != nullptr )
|
||||
{
|
||||
addrlen = sizeof(*fromAddr);
|
||||
memset(fromAddr,0,sizeof(*fromAddr));
|
||||
}
|
||||
|
||||
int fd = p->fdH != cwSOCKET_NULL_SOCK ? p->fdH : p->sockH;
|
||||
|
||||
if((bytesN = recvfrom(fd, buf, bufByteCnt, 0, (struct sockaddr*)fromAddr, &addrlen)) < 0 )
|
||||
{
|
||||
// if this is a non-blocking socket then return value -1 indicates that no data is available.
|
||||
if( cwIsNotFlag( p->flags, kBlockingFl) && bytesN == -1)
|
||||
bytesN = 0;
|
||||
else
|
||||
{
|
||||
rc = cwLogSysError(kReadFailRC,errno,"recvfrom() failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
}
|
||||
|
||||
if( recvByteCntRef != nullptr )
|
||||
*recvByteCntRef = bytesN;
|
||||
|
||||
errLabel:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
cw::rc_t cw::net::socket::initAddr( handle_t h, const char* addrStr, portNumber_t portNumber, struct sockaddr_in* retAddrPtr )
|
||||
{
|
||||
|
@ -14,10 +14,16 @@ namespace cw
|
||||
|
||||
enum
|
||||
{
|
||||
kNonBlockingFl = 0x00, // create a non-blocking socket
|
||||
kBlockingFl = 0x01, // create a blocking socket
|
||||
kTcpFl = 0x02, // create a TCP socket rather than a UDP socket
|
||||
kBroadcastFl = 0x04
|
||||
kNonBlockingFl = 0x000, // create a non-blocking socket
|
||||
kBlockingFl = 0x001, // create a blocking socket
|
||||
kTcpFl = 0x002, // create a TCP socket rather than a UDP socket
|
||||
kBroadcastFl = 0x004,
|
||||
kReuseAddrFl = 0x008,
|
||||
kReusePortFl = 0x010,
|
||||
kMultiCastTtlFl = 0x020,
|
||||
kMultiCastLoopFl = 0x040,
|
||||
kListenFl = 0x080,
|
||||
kStreamFl = 0x100
|
||||
};
|
||||
|
||||
enum
|
||||
@ -36,6 +42,13 @@ namespace cw
|
||||
|
||||
rc_t destroy( handle_t& hRef );
|
||||
|
||||
rc_t join_multicast_group( handle_t h, const char* addr );
|
||||
|
||||
rc_t setTimeOutMs( handle_t h, unsigned timeOutMs );
|
||||
|
||||
// Listen for a connections
|
||||
rc_t accept( handle_t h );
|
||||
|
||||
// Set a destination address for this socket. Once a destination address is set
|
||||
// the caller may use send() to communicate with the specified remote socket
|
||||
// without having to specify a destination address on each call.
|
||||
@ -64,6 +77,8 @@ namespace cw
|
||||
//
|
||||
rc_t select_recieve(handle_t h, char* buf, unsigned bufByteCnt, unsigned timeOutMs, unsigned* recvByteCntRef=nullptr, struct sockaddr_in* fromAddr=nullptr );
|
||||
|
||||
//
|
||||
rc_t recv_from(handle_t h, char* buf, unsigned bufByteCnt, unsigned* recvByteCntRef=nullptr, struct sockaddr_in* fromAddr=nullptr );
|
||||
|
||||
// Prepare a struct sockadddr_in for use with send()
|
||||
rc_t initAddr( handle_t h, const char* addrStr, portNumber_t portNumber, struct sockaddr_in* retAddrPtr );
|
||||
|
@ -46,8 +46,17 @@ namespace cw
|
||||
socksrv_t* p = static_cast<socksrv_t*>(arg);
|
||||
unsigned rcvByteCnt = 0;
|
||||
struct sockaddr_in fromAddr;
|
||||
rc_t rc = kOkRC;
|
||||
|
||||
if( select_recieve(p->sockH, p->recvBuf, p->recvBufByteCnt, p->timeOutMs, &rcvByteCnt, &fromAddr ) == kOkRC )
|
||||
if( p->timeOutMs == 0 )
|
||||
{
|
||||
rc = recv_from(p->sockH, p->recvBuf, p->recvBufByteCnt, &rcvByteCnt, &fromAddr );
|
||||
sleepMs(100);
|
||||
}
|
||||
else
|
||||
rc = select_recieve(p->sockH, p->recvBuf, p->recvBufByteCnt, p->timeOutMs, &rcvByteCnt, &fromAddr );
|
||||
|
||||
if( rc == kOkRC )
|
||||
if( rcvByteCnt>0 && p->cbFunc != nullptr )
|
||||
p->cbFunc( p->cbArg, p->recvBuf, rcvByteCnt, &fromAddr );
|
||||
|
||||
@ -74,7 +83,7 @@ cw::rc_t cw::net::srv::create(
|
||||
|
||||
socksrv_t* p = mem::allocZ<socksrv_t>();
|
||||
|
||||
if((rc = socket::create( p->sockH, port, socket::kNonBlockingFl, 0, remoteAddr, remotePort )) != kOkRC )
|
||||
if((rc = socket::create( p->sockH, port, flags, timeOutMs, remoteAddr, remotePort )) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
if((rc = thread::create( p->threadH, _threadFunc, p )) != kOkRC )
|
||||
|
@ -7,7 +7,7 @@ namespace cw
|
||||
{
|
||||
namespace srv
|
||||
{
|
||||
typedef void (*cbFunc_t)( void* cbArg, const char* data, unsigned dataByteCnt, const struct sockaddr_in* fromAddr );
|
||||
typedef void (*cbFunc_t)( void* cbArg, const void* data, unsigned dataByteCnt, const struct sockaddr_in* fromAddr );
|
||||
typedef handle< struct socksrv_str > handle_t;
|
||||
|
||||
rc_t create( handle_t& hRef, //
|
||||
|
@ -24,9 +24,12 @@ namespace cw
|
||||
handle_t sockH;
|
||||
thread::handle_t threadH;
|
||||
unsigned cbN;
|
||||
bool serverFl;
|
||||
bool readyFl;
|
||||
bool connectedFl;
|
||||
} app_t;
|
||||
|
||||
bool _threadFunc( void* arg )
|
||||
|
||||
bool _dgramThreadFunc( void* arg )
|
||||
{
|
||||
rc_t rc;
|
||||
app_t* app = static_cast<app_t*>(arg);
|
||||
@ -48,6 +51,57 @@ namespace cw
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _tcpStreamThreadFunc( void* arg )
|
||||
{
|
||||
rc_t rc;
|
||||
app_t* app = static_cast<app_t*>(arg);
|
||||
char buf[ app->recvBufByteN ];
|
||||
unsigned recvBufByteN = 0;
|
||||
|
||||
if( !app->serverFl )
|
||||
{
|
||||
// the client node has nothing to do because it does not receive (it only sends)
|
||||
sleepMs(50);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( app->connectedFl == false )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
// if the server disconnects then recvBufByteN
|
||||
if( recvBufByteN==0 )
|
||||
{
|
||||
app->connectedFl = false;
|
||||
}
|
||||
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 ? "+" : ".");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -68,7 +122,7 @@ cw::rc_t cw::net::socket::test( portNumber_t localPort, const char* remoteAddr,
|
||||
if((rc = create(app.sockH,localPort, kBlockingFl,timeOutMs, NULL, kInvalidPortNumber )) != kOkRC )
|
||||
return rc;
|
||||
|
||||
if((rc = thread::create( app.threadH, _threadFunc, &app )) != kOkRC )
|
||||
if((rc = thread::create( app.threadH, _dgramThreadFunc, &app )) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
if((rc = thread::unpause( app.threadH )) != kOkRC )
|
||||
@ -95,26 +149,107 @@ cw::rc_t cw::net::socket::test( portNumber_t localPort, const char* remoteAddr,
|
||||
return rcSelect(rc,rc0,rc1);
|
||||
}
|
||||
|
||||
|
||||
cw::rc_t cw::net::socket::test_tcp( portNumber_t localPort, const char* remoteAddr, portNumber_t remotePort, bool dgramFl, bool serverFl )
|
||||
{
|
||||
rc_t rc;
|
||||
unsigned timeOutMs = 100;
|
||||
const unsigned sbufN = 31;
|
||||
char sbuf[ sbufN+1 ];
|
||||
app_t app;
|
||||
bool streamFl = !dgramFl;
|
||||
bool clientFl = !serverFl;
|
||||
unsigned flags = kTcpFl | kBlockingFl;
|
||||
|
||||
app.cbN = 0;
|
||||
app.recvBufByteN = sbufN+1;
|
||||
app.serverFl = serverFl;
|
||||
app.readyFl = false;
|
||||
app.connectedFl = false;
|
||||
|
||||
if( serverFl && streamFl )
|
||||
flags |= kListenFl;
|
||||
|
||||
if( streamFl )
|
||||
flags |= kStreamFl;
|
||||
|
||||
// create the socket
|
||||
if((rc = create(app.sockH,localPort, flags,timeOutMs, NULL, kInvalidPortNumber )) != kOkRC )
|
||||
return rc;
|
||||
|
||||
// create the listening thread (which is really only used by the server)
|
||||
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( streamFl && clientFl )
|
||||
{
|
||||
if((rc = connect(app.sockH,remoteAddr,remotePort)) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
app.connectedFl = true;
|
||||
}
|
||||
|
||||
printf("Starting node ....\n");
|
||||
|
||||
// start the thread
|
||||
if((rc = thread::unpause( app.threadH )) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
|
||||
while( true )
|
||||
{
|
||||
printf("? ");
|
||||
if( std::fgets(sbuf,sbufN,stdin) == sbuf )
|
||||
{
|
||||
if( strcmp(sbuf,"quit\n") == 0)
|
||||
break;
|
||||
|
||||
// when using streams only the client can send
|
||||
if( streamFl & clientFl )
|
||||
{
|
||||
printf("Sending:%s",sbuf);
|
||||
send(app.sockH, sbuf, strlen(sbuf)+1 );
|
||||
}
|
||||
|
||||
// when using dgrams the dest. address is need to send
|
||||
if( dgramFl )
|
||||
{
|
||||
printf("Sending:%s",sbuf);
|
||||
send(app.sockH, sbuf, strlen(sbuf)+1, remoteAddr, remotePort);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
errLabel:
|
||||
rc_t rc0 = thread::destroy(app.threadH);
|
||||
|
||||
rc_t rc1 = destroy(app.sockH);
|
||||
|
||||
return rcSelect(rc,rc0,rc1);
|
||||
}
|
||||
|
||||
|
||||
namespace cw
|
||||
{
|
||||
namespace net
|
||||
{
|
||||
namespace srv
|
||||
{
|
||||
typedef struct app_str
|
||||
{
|
||||
handle_t srvH;
|
||||
unsigned cbN;
|
||||
} app_t;
|
||||
typedef struct app_str
|
||||
{
|
||||
handle_t srvH;
|
||||
unsigned cbN;
|
||||
} app_t;
|
||||
|
||||
void srvRecieveCallback( void* arg, const char* data, unsigned dataByteCnt, const struct sockaddr_in* fromAddr )
|
||||
{
|
||||
app_t* p = static_cast<app_t*>(arg);
|
||||
char addrBuf[ INET_ADDRSTRLEN ];
|
||||
socket::addrToString( fromAddr, addrBuf, INET_ADDRSTRLEN );
|
||||
p->cbN += 1;
|
||||
printf("%i %s %s", p->cbN, addrBuf, data );
|
||||
}
|
||||
void srvRecieveCallback( void* arg, const void* data, unsigned dataByteCnt, const struct sockaddr_in* fromAddr )
|
||||
{
|
||||
app_t* p = static_cast<app_t*>(arg);
|
||||
char addrBuf[ INET_ADDRSTRLEN ];
|
||||
socket::addrToString( fromAddr, addrBuf, INET_ADDRSTRLEN );
|
||||
p->cbN += 1;
|
||||
printf("%i %s %s", p->cbN, addrBuf, (const char*)data );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -153,3 +288,6 @@ cw::rc_t cw::net::srv::test( socket::portNumber_t localPort, const char* remoteA
|
||||
|
||||
return rcSelect(rc,rc0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -8,11 +8,13 @@ namespace cw
|
||||
namespace socket
|
||||
{
|
||||
rc_t test( portNumber_t localPort, const char* remoteAddr, portNumber_t remotePort );
|
||||
rc_t test_tcp( portNumber_t localPort, const char* remoteAddr, portNumber_t remotePort, bool dgramFl, bool serverFl );
|
||||
}
|
||||
|
||||
namespace srv
|
||||
{
|
||||
rc_t test( socket::portNumber_t localPort, const char* remoteAddr, socket::portNumber_t remotePort );
|
||||
rc_t test( socket::portNumber_t localPort, const char* remoteAddr, socket::portNumber_t remotePort );
|
||||
rc_t mdns_test();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user