19 #define _WINSOCK_DEPRECATED_NO_WARNINGS    23 #pragma comment(lib, "WS2_32.LIB")    27 #define INVALID_SOCKET (-1)    28 #include <arpa/inet.h>    31 #include <netinet/in.h>    32 #include <netinet/tcp.h>    33 #include <sys/ioctl.h>    34 #include <sys/socket.h>    35 #include <sys/types.h>    54     WORD wVersionRequested;
    57     wVersionRequested = MAKEWORD(2, 0);
    59     if (WSAStartup(wVersionRequested, &wsaData))
    62     m_hSock = INVALID_SOCKET;
    76     catch (
const std::exception& e)
    78         std::cerr << 
"[~CClientTCPSocket] Exception:\n"    94     if (m_hSock != INVALID_SOCKET)
    98         m_hSock = INVALID_SOCKET;
   104         shutdown(m_hSock, SHUT_RDWR);
   119     return readAsync(Buffer, Count);
   131     return writeAsync(Buffer, Count);
   138     Write(str.c_str(), str.size());
   145     const std::string& remotePartAddress, 
unsigned short remotePartTCPPort,
   146     unsigned int timeout_ms)
   151     if (m_hSock != INVALID_SOCKET) close();
   154     if (INVALID_SOCKET == (m_hSock = socket(AF_INET, SOCK_STREAM, 0)))
   156             "Error creating new client socket:\n%s",
   157             getLastErrorStr().c_str()));
   159     struct sockaddr_in otherAddress;
   161     otherAddress.sin_family = AF_INET;
   162     otherAddress.sin_port = htons(remotePartTCPPort);
   165     std::string solved_IP;
   167             remotePartAddress, solved_IP, DNS_LOOKUP_TIMEOUT_MS))
   169             "DNS lookup failed for '%s'", remotePartAddress.c_str());
   172     otherAddress.sin_addr.s_addr = inet_addr(solved_IP.c_str());
   173     if (INADDR_NONE == otherAddress.sin_addr.s_addr)
   175             "Invalid IP address provided: %s", solved_IP.c_str());
   179     unsigned long non_block_mode = 1;
   180     if (ioctlsocket(m_hSock, FIONBIO, &non_block_mode))
   181         THROW_EXCEPTION(
"Error entering non-blocking mode with ioctlsocket();");
   183     int oldflags = fcntl(m_hSock, F_GETFL, 0);
   184     if (oldflags == -1) 
THROW_EXCEPTION(
"Error retrieving fcntl();of socket.");
   185     oldflags |= O_NONBLOCK;  
   186     if (-1 == fcntl(m_hSock, F_SETFL, oldflags))
   192         m_hSock, (
struct sockaddr*)&otherAddress, 
sizeof(otherAddress));
   194     int er = WSAGetLastError();
   195     if (r < 0 && er != WSAEINPROGRESS && er != WSAEWOULDBLOCK)
   198     if (r < 0 && er != EINPROGRESS)
   201             "Error connecting to %s:%hu. Error: %s [%d]",
   202             remotePartAddress.c_str(), remotePartTCPPort, strerror(er), er));
   205     timeval timer = {0, 0};
   206     fd_set ss_write, ss_errors;
   209     FD_SET(m_hSock, &ss_write);
   210     FD_SET(m_hSock, &ss_errors);
   212     timer.tv_sec = timeout_ms / 1000;
   213     timer.tv_usec = 1000 * (timeout_ms % 1000);
   215     int sel_ret = select(
   220         timeout_ms == 0 ? 
nullptr : &timer);
   224             "Timeout connecting to '%s:%hu':\n%s", remotePartAddress.c_str(),
   225             remotePartTCPPort, getLastErrorStr().c_str()));
   228             "Error connecting to '%s:%hu':\n%s", remotePartAddress.c_str(),
   229             remotePartTCPPort, getLastErrorStr().c_str()));
   234     int lon = 
sizeof(int);
   235     getsockopt(m_hSock, SOL_SOCKET, SO_ERROR, (
char*)(&valopt), &
lon);
   238     getsockopt(m_hSock, SOL_SOCKET, SO_ERROR, (
void*)(&valopt), &
lon);
   244             "Error connecting to %s:%hu. Error: %i.", remotePartAddress.c_str(),
   245             remotePartTCPPort, valopt));
   249             "Error connecting to %s:%hu. Error: %s.", remotePartAddress.c_str(),
   250             remotePartTCPPort, strerror(valopt)));
   257     if (ioctlsocket(m_hSock, FIONBIO, &non_block_mode))
   260     oldflags &= ~O_NONBLOCK;  
   261     if (-1 == fcntl(m_hSock, F_SETFL, oldflags))
   266     m_remotePartIP = remotePartAddress;
   279     void* Buffer, 
const size_t Count, 
const int timeoutStart_ms,
   280     const int timeoutBetween_ms)
   284     if (m_hSock == INVALID_SOCKET) 
return 0;  
   286     size_t remainToRead, alreadyRead = 0;
   288     bool timeoutExpired = 
false;
   290     struct timeval timeoutSelect = {0, 0};
   291     struct timeval* ptrTimeout;
   296     FD_SET(m_hSock, &sockArr);
   299     while (alreadyRead < Count && !timeoutExpired)
   302         int curTimeout = alreadyRead == 0 ? timeoutStart_ms : timeoutBetween_ms;
   305             ptrTimeout = 
nullptr;
   308             timeoutSelect.tv_sec = curTimeout / 1000;
   309             timeoutSelect.tv_usec = 1000 * (curTimeout % 1000);
   310             ptrTimeout = &timeoutSelect;
   314         int selRet = ::select(
   321         if (selRet == INVALID_SOCKET)
   323                 "Error reading from socket: %s", getLastErrorStr().c_str());
   328             timeoutExpired = 
true;
   333             remainToRead = Count - alreadyRead;
   337                 m_hSock, ((
char*)Buffer) + alreadyRead, (
int)remainToRead, 0);
   339             if (readNow != INVALID_SOCKET)
   342                 alreadyRead += readNow;
   351             if (readNow == 0 && remainToRead != 0)
   355                 timeoutExpired = 
true;
   370     const void* Buffer, 
const size_t Count, 
const int timeout_ms)
   374     if (m_hSock == INVALID_SOCKET) 
return 0;  
   376     size_t remainToWrite, alreadyWritten = 0;
   378     bool timeoutExpired = 
false;
   380     struct timeval timeoutSelect = {0, 0};
   381     struct timeval* ptrTimeout;
   386     FD_SET(m_hSock, &sockArr);
   391         ptrTimeout = 
nullptr;
   395         timeoutSelect.tv_sec = timeout_ms / 1000;
   396         timeoutSelect.tv_usec = 1000 * (timeout_ms % 1000);
   397         ptrTimeout = &timeoutSelect;
   401     while (alreadyWritten < Count && !timeoutExpired)
   404         int selRet = ::select(
   411         if (selRet == INVALID_SOCKET)
   413                 "Error writing to socket: %s", getLastErrorStr().c_str());
   418             timeoutExpired = 
true;
   425             remainToWrite = Count - alreadyWritten;
   429                 m_hSock, ((
char*)Buffer) + alreadyWritten, (
int)remainToWrite,
   432             if (writtenNow != INVALID_SOCKET)
   435                 alreadyWritten += writtenNow;
   441     return alreadyWritten;
   451     if (m_hSock == INVALID_SOCKET) 
return 0;  
   452     unsigned long ret = 0;
   455         ioctlsocket(m_hSock, FIONREAD, &ret)
   457         ioctl(m_hSock, FIONREAD, &ret)
   472     int length = 
sizeof(newValue);
   475         m_hSock, IPPROTO_TCP, TCP_NODELAY, (
char*)&newValue, length);
   485     int length = 
sizeof(value);
   487     unsigned int length = 
sizeof(value);
   490         getsockopt(m_hSock, IPPROTO_TCP, TCP_NODELAY, (
char*)&value, &length);
   503     const unsigned int length = 
sizeof(newValue);
   505     return setsockopt(m_hSock, SOL_SOCKET, SO_SNDBUF, (
char*)&newValue, length);
   515     int length = 
sizeof(value);
   517     unsigned int length = 
sizeof(value);
   519     getsockopt(m_hSock, SOL_SOCKET, SO_SNDBUF, (
char*)&value, &length);
   530     [[maybe_unused]] int64_t off, [[maybe_unused]] CStream::TSeekOrigin org)
 static unsigned int DNS_LOOKUP_TIMEOUT_MS
See description of CClientTCPSocket. 
 
int setSOSendBufffer(int newValue)
Set the size of the SO send buffer. 
 
void connect(const std::string &remotePartAddress, unsigned short remotePartTCPPort, unsigned int timeout_ms=0)
Establishes a connection with a remote part. 
 
size_t Write(const void *Buffer, size_t Count) override
Introduces a virtual method responsible for writing to the stream. 
 
#define THROW_EXCEPTION(msg)
 
std::string std::string format(std::string_view fmt, ARGS &&... args)
 
bool isConnected()
Returns true if this objects represents a successfully connected socket. 
 
uint64_t Seek(int64_t off, CStream::TSeekOrigin org=sFromBeginning) override
This virtual method has no effect in this implementation over a TCP socket, and its use raises an exc...
 
std::string getLastSocketErrorStr()
Returns a description of the last Sockets error. 
 
int getSOSendBufffer()
Return the current size of the SO send buffer. 
 
size_t Read(void *Buffer, size_t Count) override
Introduces a virtual method responsible for reading from the stream (This method BLOCKS) This method ...
 
uint64_t getTotalBytesCount() const override
This virtual method has no effect in this implementation over a TCP socket, and its use raises an exc...
 
~CClientTCPSocket() override
Destructor. 
 
bool DNS_resolve_async(const std::string &server_name, std::string &out_ip, const unsigned int timeout_ms=3000)
Resolve a server address by its name, returning its IP address as a string - This method has a timeou...
 
CClientTCPSocket()
Default constructor. 
 
int getTCPNoDelay()
Return the value of the TCPNoDelay option. 
 
std::string getLastErrorStr()
Returns a description of the last Sockets error. 
 
size_t writeAsync(const void *Buffer, const size_t Count, const int timeout_ms=-1)
A method for writing to the socket with optional timeouts. 
 
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries. 
 
int setTCPNoDelay(int newValue)
Set the TCP no delay option of the protocol (Nagle algorithm). 
 
uint64_t getPosition() const override
This virtual method has no effect in this implementation over a TCP socket, and its use raises an exc...
 
void close()
Closes the connection. 
 
std::string exception_to_str(const std::exception &e)
Builds a nice textual representation of a nested exception, which if generated using MRPT macros (THR...
 
size_t getReadPendingBytes()
Return the number of bytes already in the receive queue (they can be read without waiting) ...
 
Serial and networking devices and utilities. 
 
size_t readAsync(void *Buffer, const size_t Count, const int timeoutStart_ms=-1, const int timeoutBetween_ms=-1)
A method for reading from the socket with an optional timeout. 
 
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
 
void sendString(const std::string &str)
Writes a string to the socket.