From 6590d4b181d839f68c7ffc3191aca6221b138c23 Mon Sep 17 00:00:00 2001 From: kpl Date: Mon, 27 Jan 2020 17:52:53 -0500 Subject: [PATCH] cwTcpSocket*.h/cpp : Updated to support more socket options and configurations. --- cwTcpSocket.cpp | 279 ++++++++++++++++++++++++++++++++++++++------ cwTcpSocket.h | 23 +++- cwTcpSocketSrv.cpp | 13 ++- cwTcpSocketSrv.h | 2 +- cwTcpSocketTest.cpp | 170 ++++++++++++++++++++++++--- cwTcpSocketTest.h | 4 +- 6 files changed, 429 insertions(+), 62 deletions(-) diff --git a/cwTcpSocket.cpp b/cwTcpSocket.cpp index e5be0f7..c459884 100644 --- a/cwTcpSocket.cpp +++ b/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(); 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 ) { diff --git a/cwTcpSocket.h b/cwTcpSocket.h index c4309af..1fd6622 100644 --- a/cwTcpSocket.h +++ b/cwTcpSocket.h @@ -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 ); diff --git a/cwTcpSocketSrv.cpp b/cwTcpSocketSrv.cpp index 302f337..2e76991 100644 --- a/cwTcpSocketSrv.cpp +++ b/cwTcpSocketSrv.cpp @@ -46,8 +46,17 @@ namespace cw socksrv_t* p = static_cast(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(); - 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 ) diff --git a/cwTcpSocketSrv.h b/cwTcpSocketSrv.h index a7192be..680ad84 100644 --- a/cwTcpSocketSrv.h +++ b/cwTcpSocketSrv.h @@ -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, // diff --git a/cwTcpSocketTest.cpp b/cwTcpSocketTest.cpp index cdf63a0..f5df924 100644 --- a/cwTcpSocketTest.cpp +++ b/cwTcpSocketTest.cpp @@ -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(arg); @@ -48,6 +51,57 @@ namespace cw fflush(stdout); } + return true; + } + + bool _tcpStreamThreadFunc( void* arg ) + { + rc_t rc; + app_t* app = static_cast(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(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(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); } + + + diff --git a/cwTcpSocketTest.h b/cwTcpSocketTest.h index a9129d3..8352363 100644 --- a/cwTcpSocketTest.h +++ b/cwTcpSocketTest.h @@ -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(); } } }