From f011324f8d3dbf102c4cf4fde465a8b80ece319e Mon Sep 17 00:00:00 2001 From: hayati ayguen Date: Sun, 13 May 2018 01:03:32 +0200 Subject: [PATCH] bugfixes and enhancements on local/peer and bind() * fixed CSimpleSocket::GetClientPort() * fixed peer/local address in CPassiveSocket::Accept() * fixed Linux compilation in CPassiveSocket::Listen() * added CSimpleSocket::Bind() for tcp/udp client connections * enhanced all examples: all print local/peer address and port * fixed output of GetLocalAddr() and GetPeerAddr() in examples * examples txtoserver and txtoudpserver with optional local binding Signed-off-by: hayati ayguen --- examples/DelayedEchoServer.cpp | 17 ++++++- examples/EchoServer.cpp | 23 ++++++--- examples/QueryDayTime.cpp | 5 ++ examples/TxToServer.cpp | 18 ++++--- examples/TxToUdpServer.cpp | 18 ++++--- examples/UdpServer.cpp | 26 +++++++--- src/SimpleSocket.cpp | 90 ++++++++++++++++++++++++++-------- src/SimpleSocket.h | 25 ++++++++-- 8 files changed, 173 insertions(+), 49 deletions(-) diff --git a/examples/DelayedEchoServer.cpp b/examples/DelayedEchoServer.cpp index 2e8e0dd..84f1c10 100644 --- a/examples/DelayedEchoServer.cpp +++ b/examples/DelayedEchoServer.cpp @@ -20,16 +20,31 @@ int main(int argc, char **argv) CPassiveSocket socket; CSimpleSocket *pClient = NULL; + const char * bindAddr = 0; + unsigned bindPort = 6789; + if ( argc <= 1 ) + fprintf(stderr, "usage: %s [ []]\n", argv[0] ); + if ( 1 < argc ) + bindAddr = argv[1]; + if ( 2 < argc ) + bindPort = atoi(argv[2]) & 65535; + //-------------------------------------------------------------------------- // Initialize our socket object //-------------------------------------------------------------------------- socket.Initialize(); - socket.Listen( 0, 6789 ); // NULL (not "127.0.0.1") to allow testing with remotes + fprintf(stderr, "binding to %s:%u\n", bindAddr, bindPort); + socket.Listen( bindAddr, uint16(bindPort) ); // not "127.0.0.1" to allow testing with remotes while (true) { if ((pClient = socket.Accept()) != NULL) { + fprintf(stderr, "\nLocal is %s. Local: %s:%u " + , ( pClient->IsServerSide() ? "Server" : "Client" ) + , pClient->GetLocalAddr(), (unsigned)pClient->GetLocalPort()); + fprintf(stderr, "Peer: %s:%u\n", pClient->GetPeerAddr(), (unsigned)pClient->GetPeerPort()); + //---------------------------------------------------------------------- // Receive request from the client. //---------------------------------------------------------------------- diff --git a/examples/EchoServer.cpp b/examples/EchoServer.cpp index b491e3c..b99dae9 100644 --- a/examples/EchoServer.cpp +++ b/examples/EchoServer.cpp @@ -8,16 +8,31 @@ int main(int argc, char **argv) CPassiveSocket socket; CActiveSocket *pClient = NULL; + const char * bindAddr = 0; + unsigned bindPort = 6789; + if ( argc <= 1 ) + fprintf(stderr, "usage: %s [ []]\n", argv[0] ); + if ( 1 < argc ) + bindAddr = argv[1]; + if ( 2 < argc ) + bindPort = atoi(argv[2]) & 65535; + //-------------------------------------------------------------------------- // Initialize our socket object //-------------------------------------------------------------------------- socket.Initialize(); - socket.Listen( 0, 6789 ); // NULL (not "127.0.0.1") to allow testing with remotes + fprintf(stderr, "binding to %s:%u\n", bindAddr, bindPort); + socket.Listen( bindAddr, uint16(bindPort) ); // not "127.0.0.1" to allow testing with remotes while (true) { if ((pClient = socket.Accept()) != NULL) { + fprintf(stderr, "\nLocal is %s. Local: %s:%u " + , ( pClient->IsServerSide() ? "Server" : "Client" ) + , pClient->GetLocalAddr(), (unsigned)pClient->GetLocalPort()); + fprintf(stderr, "Peer: %s:%u\n", pClient->GetPeerAddr(), (unsigned)pClient->GetPeerPort()); + //---------------------------------------------------------------------- // Receive request from the client. //---------------------------------------------------------------------- @@ -27,12 +42,6 @@ int main(int argc, char **argv) if (pClient->Receive(MAX_PACKET)) { - fprintf(stderr, "\n%s. Local: %s:%u Peer: %s:%u\n" - , ( pClient->IsServerSide() ? "Local is Server" : "Local is Client" ) - , pClient->GetLocalAddr(), (unsigned)pClient->GetLocalPort() - , pClient->GetPeerAddr(), (unsigned)pClient->GetPeerPort() - ); - //------------------------------------------------------------------ // Send response to client and close connection to the client. //------------------------------------------------------------------ diff --git a/examples/QueryDayTime.cpp b/examples/QueryDayTime.cpp index 254d6e1..a914cf5 100644 --- a/examples/QueryDayTime.cpp +++ b/examples/QueryDayTime.cpp @@ -23,6 +23,11 @@ int main(int argc, char **argv) fprintf(stderr, "trying to connect to timeserver %s:%d ..\n", timeServer, PortNo); if (socket.Open(timeServer, (uint16)PortNo)) { + fprintf(stderr, "\nLocal is %s. Local: %s:%u " + , ( socket.IsServerSide() ? "Server" : "Client" ) + , socket.GetLocalAddr(), (unsigned)socket.GetLocalPort()); + fprintf(stderr, "Peer: %s:%u\n", socket.GetPeerAddr(), (unsigned)socket.GetPeerPort()); + //---------------------------------------------------------------------- // Send a requtest the server requesting the current time. //---------------------------------------------------------------------- diff --git a/examples/TxToServer.cpp b/examples/TxToServer.cpp index 4fd7064..0706ac5 100644 --- a/examples/TxToServer.cpp +++ b/examples/TxToServer.cpp @@ -11,7 +11,7 @@ int main(int argc, char **argv) if ( argc < 3 ) { - fprintf(stderr, "usage: %s \n", argv[0] ); + fprintf(stderr, "usage: %s [ ]\n", argv[0] ); return 10; } @@ -20,6 +20,13 @@ int main(int argc, char **argv) //-------------------------------------------------------------------------- socket.Initialize(); + if ( 4 < argc ) + { + unsigned bindPort = atoi(argv[4]); + bool ret = socket.Bind( argv[3], uint16(bindPort) ); + fprintf(stderr, "bind to %s:%u %s\n", argv[3], bindPort, (ret ? "successful":"failed") ); + } + bool bConnOK = socket.Open( argv[1], 6789 ); if ( !bConnOK ) { @@ -27,11 +34,10 @@ int main(int argc, char **argv) return 10; } - fprintf(stderr, "\n%s. Local: %s:%u Peer: %s:%u\n" - , ( socket.IsServerSide() ? "Local is Server" : "Local is Client" ) - , socket.GetLocalAddr(), (unsigned)socket.GetLocalPort() - , socket.GetPeerAddr(), (unsigned)socket.GetPeerPort() - ); + fprintf(stderr, "\nLocal is %s. Local: %s:%u " + , ( socket.IsServerSide() ? "Server" : "Client" ) + , socket.GetLocalAddr(), (unsigned)socket.GetLocalPort()); + fprintf(stderr, "Peer: %s:%u\n", socket.GetPeerAddr(), (unsigned)socket.GetPeerPort()); uint32 nSendBufSize = socket.GetSendWindowSize(); fprintf(stderr, "default Send Buffer Size %u\n", nSendBufSize ); diff --git a/examples/TxToUdpServer.cpp b/examples/TxToUdpServer.cpp index 66bff2d..5b75eb5 100644 --- a/examples/TxToUdpServer.cpp +++ b/examples/TxToUdpServer.cpp @@ -11,7 +11,7 @@ int main(int argc, char **argv) if ( argc < 3 ) { - fprintf(stderr, "usage: %s \n", argv[0] ); + fprintf(stderr, "usage: %s [ ]\n", argv[0] ); return 10; } @@ -20,6 +20,13 @@ int main(int argc, char **argv) //-------------------------------------------------------------------------- socket.Initialize(); + if ( 4 < argc ) + { + unsigned bindPort = atoi(argv[4]); + bool ret = socket.Bind( argv[3], uint16(bindPort) ); + fprintf(stderr, "bind to %s:%u %s\n", argv[3], bindPort, (ret ? "successful":"failed") ); + } + bool bConnOK = socket.Open( argv[1], 6789 ); if ( !bConnOK ) { @@ -27,11 +34,10 @@ int main(int argc, char **argv) return 10; } - fprintf(stderr, "\n%s. Local: %s:%u Peer: %s:%u\n" - , ( socket.IsServerSide() ? "Local is Server" : "Local is Client" ) - , socket.GetLocalAddr(), (unsigned)socket.GetLocalPort() - , socket.GetPeerAddr(), (unsigned)socket.GetPeerPort() - ); + fprintf(stderr, "\nLocal is %s. Local: %s:%u " + , ( socket.IsServerSide() ? "Server" : "Client" ) + , socket.GetLocalAddr(), (unsigned)socket.GetLocalPort()); + fprintf(stderr, "Peer: %s:%u\n", socket.GetPeerAddr(), (unsigned)socket.GetPeerPort()); size_t sendSize = strlen( argv[2] ); socket.Send( argv[2], (int32)sendSize ); diff --git a/examples/UdpServer.cpp b/examples/UdpServer.cpp index cbe7105..3e0bbc3 100644 --- a/examples/UdpServer.cpp +++ b/examples/UdpServer.cpp @@ -8,13 +8,28 @@ int main(int argc, char **argv) char buffer[ MAX_PACKET ]; CPassiveSocket passiveSocket( CSimpleSocket::SocketTypeUdp ); + const char * bindAddr = 0; + unsigned bindPort = 6789; + if ( argc <= 1 ) + fprintf(stderr, "usage: %s [ []]\n", argv[0] ); + if ( 1 < argc ) + bindAddr = argv[1]; + if ( 2 < argc ) + bindPort = atoi(argv[2]) & 65535; + //-------------------------------------------------------------------------- // Initialize our socket object //-------------------------------------------------------------------------- passiveSocket.Initialize(); - passiveSocket.Bind( 0, 6789 ); // NULL (not "127.0.0.1") to allow testing with remotes + fprintf(stderr, "binding to %s:%u\n", bindAddr, bindPort); + passiveSocket.Bind( bindAddr, uint16(bindPort) ); // not "127.0.0.1" to allow testing with remotes CSimpleSocket &socket = passiveSocket; + fprintf(stderr, "\nLocal is %s. Local: %s:%u " + , ( socket.IsServerSide() ? "Server" : "Client" ) + , socket.GetLocalAddr(), (unsigned)socket.GetLocalPort()); + fprintf(stderr, "(invalid) Peer: %s:%u\n", socket.GetPeerAddr(), (unsigned)socket.GetPeerPort()); + socket.SetReceiveTimeoutMillis(500); while (true) @@ -31,11 +46,10 @@ int main(int argc, char **argv) fprintf( stderr, "GetNumReceivableBytes() = %d != %d = Receive() !\n", peekRx, rx ); if (rx > 0) { - fprintf(stderr, "\n%s. Local: %s:%u Peer: %s:%u\n" - , ( passiveSocket.IsServerSide() ? "Local is Server" : "Local is Client" ) - , passiveSocket.GetLocalAddr(), (unsigned)passiveSocket.GetLocalPort() - , passiveSocket.GetPeerAddr(), (unsigned)passiveSocket.GetPeerPort() - ); + fprintf(stderr, "\nLocal is %s. Local: %s:%u " + , ( socket.IsServerSide() ? "Server" : "Client" ) + , socket.GetLocalAddr(), (unsigned)socket.GetLocalPort()); + fprintf(stderr, "Peer: %s:%u\n", socket.GetPeerAddr(), (unsigned)socket.GetPeerPort()); fprintf(stderr, "\nreceived %d bytes:\n", rx ); for ( int k = 0; k < rx; ++k ) diff --git a/src/SimpleSocket.cpp b/src/SimpleSocket.cpp index 9624b33..525fbb0 100644 --- a/src/SimpleSocket.cpp +++ b/src/SimpleSocket.cpp @@ -256,10 +256,15 @@ CSimpleSocket::CSimpleSocket(CSocketType nType) : m_bIsServerSide(false), m_bPeerHasClosed(true) { - SetConnectTimeout(1, 0); // default timeout for connection + memset(&m_stConnectTimeout, 0, sizeof(struct timeval)); memset(&m_stRecvTimeout, 0, sizeof(struct timeval)); memset(&m_stSendTimeout, 0, sizeof(struct timeval)); memset(&m_stLinger, 0, sizeof(struct linger)); + SetConnectTimeout(1, 0); // default timeout for connection + + memset(&m_stServerSockaddr, 0, sizeof(struct sockaddr)); + memset(&m_stClientSockaddr, 0, sizeof(struct sockaddr)); + memset(&m_stMulticastGroup, 0, sizeof(struct sockaddr)); switch(nType) { @@ -834,6 +839,63 @@ bool CSimpleSocket::Open(const char *pAddr, uint16 nPort) } +//------------------------------------------------------------------------------ +// +// Bind() +// +//------------------------------------------------------------------------------ +bool CSimpleSocket::Bind(const char *pInterface, uint16 nPort) +{ + bool bRetVal = false; +#ifdef WIN32 + ULONG inAddr; +#else + in_addr_t inAddr; +#endif + + memset(&m_stClientSockaddr,0,sizeof(m_stClientSockaddr)); + m_stClientSockaddr.sin_family = AF_INET; + m_stClientSockaddr.sin_port = htons(nPort); + + //-------------------------------------------------------------------------- + // If no IP Address (interface ethn) is supplied, or the loop back is + // specified then bind to any interface, else bind to specified interface. + //-------------------------------------------------------------------------- + if (pInterface && pInterface[0]) + { + inet_pton(AF_INET, pInterface, &inAddr); + } + else + { + inAddr = INADDR_ANY; + } + + m_stClientSockaddr.sin_addr.s_addr = inAddr; + + ClearSystemError(); + + //-------------------------------------------------------------------------- + // Bind to the specified port + //-------------------------------------------------------------------------- + if (bind(m_socket, (struct sockaddr *)&m_stClientSockaddr, sizeof(m_stClientSockaddr)) == 0) + { + bRetVal = true; + } + + //-------------------------------------------------------------------------- + // If there was a socket error then close the socket to clean out the + // connection in the backlog. + //-------------------------------------------------------------------------- + TranslateSocketError(); + + if (bRetVal == false) + { + Close(); + } + + return bRetVal; +} + //------------------------------------------------------------------------------ // // BindInterface() @@ -957,7 +1019,7 @@ const char * CSimpleSocket::GetClientAddr() const /// @return client port number. uint16 CSimpleSocket::GetClientPort() const { - return m_stClientSockaddr.sin_port; + return ntohs(m_stClientSockaddr.sin_port); } /// Returns server Internet host address as a string in standard numbers-and-dots notation. @@ -1204,25 +1266,13 @@ int32 CSimpleSocket::Send(const uint8 *pBuf, size_t bytesToSend) // Check error condition and attempt to resend if call // was interrupted by a signal. //--------------------------------------------------------- - // if (GetMulticast()) - // { - // do - // { - // m_nBytesSent = SENDTO(m_socket, pBuf, bytesToSend, 0, (const sockaddr *)&m_stMulticastGroup, - // sizeof(m_stMulticastGroup)); - // TranslateSocketError(); - // } while (GetSocketError() == CSimpleSocket::SocketInterrupted); - // } - // else + do { - do - { - m_nBytesSent = SENDTO(m_socket, pBuf, bytesToSend, 0, - (const sockaddr *)&m_stServerSockaddr, - sizeof(m_stServerSockaddr)); - TranslateSocketError(); - } while (GetSocketError() == CSimpleSocket::SocketInterrupted); - } + m_nBytesSent = SENDTO(m_socket, pBuf, bytesToSend, 0, + (const sockaddr *)&m_stServerSockaddr, + sizeof(m_stServerSockaddr)); + TranslateSocketError(); + } while (GetSocketError() == CSimpleSocket::SocketInterrupted); m_timer.SetEndTime(); } diff --git a/src/SimpleSocket.h b/src/SimpleSocket.h index 8085ed1..3a965e1 100644 --- a/src/SimpleSocket.h +++ b/src/SimpleSocket.h @@ -316,15 +316,15 @@ class EXPORT CSimpleSocket { inline int32 Send(const char *pBuf, size_t bytesToSend) { return Send( (const uint8 *)pBuf, bytesToSend ); - }; + } inline int32 Transmit(const uint8 *pBuf, size_t bytesToSend) { return Send( pBuf, bytesToSend ); - }; + } inline int32 Transmit(const char *pBuf, size_t bytesToSend) { return Send( (const uint8 *)pBuf, bytesToSend ); - }; + } /// Attempts to send at most nNumItem blocks described by sendVector /// to the socket descriptor associated with the socket object. @@ -491,6 +491,13 @@ class EXPORT CSimpleSocket { /// @return true if successfully bound to interface bool BindInterface(const char *pInterface); + + /// Bind socket to a specific interface in general for tcp/udp clients + /// @param pInterface - interface on which to bind. + /// @param nPort - port on which multicast + /// @return true if able to bind to interface. + bool Bind(const char *pInterface, uint16 nPort); + /// Gets the timeout value that specifies the maximum number of seconds a /// a call to CSimpleSocket::Send waits until it completes. /// @return the length of time in seconds @@ -558,14 +565,20 @@ class EXPORT CSimpleSocket { }; /// Returns clients Internet host address as a string in standard numbers-and-dots notation. + /// on TCP Server the Client and Peer Address/Port get valid with successful Accept() + /// on UDP Server the Client and Peer Address/Port get valid with successful Receive() + /// ATTENTION: return is same static buffer as in inet_ntoa(), GetClientAddr(), GetServerAddr(), GetLocalAddr(), GetPeerAddr() /// @return NULL if invalid const char * GetClientAddr() const; /// Returns the port number on which the client is connected. + /// on TCP Server the Client and Peer Address/Port get valid with successful Accept() + /// on UDP Server the Client and Peer Address/Port get valid with successful Receive() /// @return client port number. uint16 GetClientPort() const; /// Returns server Internet host address as a string in standard numbers-and-dots notation. + /// ATTENTION: return is same static buffer as in inet_ntoa(), GetClientAddr(), GetServerAddr(), GetLocalAddr(), GetPeerAddr() /// @return NULL if invalid const char * GetServerAddr() const; @@ -577,6 +590,7 @@ class EXPORT CSimpleSocket { bool IsServerSide() const; /// Returns local Internet host address as a string in standard numbers-and-dots notation. + /// ATTENTION: return is same static buffer as in inet_ntoa(), GetClientAddr(), GetServerAddr(), GetLocalAddr(), GetPeerAddr() /// @return NULL if invalid const char * GetLocalAddr() const; @@ -586,10 +600,15 @@ class EXPORT CSimpleSocket { /// Returns Peer's Internet host address as a string in standard numbers-and-dots notation. + /// on TCP Server the Client and Peer Address/Port get valid with successful Accept() + /// on UDP Server the Client and Peer Address/Port get valid with successful Receive() + /// ATTENTION: return is same static buffer as in inet_ntoa(), GetClientAddr(), GetServerAddr(), GetLocalAddr(), GetPeerAddr() /// @return NULL if invalid const char * GetPeerAddr() const; /// Returns the port number on which the peer is connected. + /// on TCP Server the Client and Peer Address/Port get valid with successful Accept() + /// on UDP Server the Client and Peer Address/Port get valid with successful Receive() /// @return client port number. uint16 GetPeerPort() const;