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;
87 if (m_hSock != INVALID_SOCKET)
91 m_hSock = INVALID_SOCKET;
97 shutdown(m_hSock, SHUT_RDWR);
112 return readAsync(Buffer, Count);
124 return writeAsync(Buffer, Count);
131 Write(str.c_str(), str.size());
138 const std::string& remotePartAddress,
unsigned short remotePartTCPPort,
139 unsigned int timeout_ms)
144 if (m_hSock != INVALID_SOCKET) close();
147 if (INVALID_SOCKET == (m_hSock = socket(AF_INET, SOCK_STREAM, 0)))
149 "Error creating new client socket:\n%s",
150 getLastErrorStr().c_str()));
152 struct sockaddr_in otherAddress;
154 otherAddress.sin_family = AF_INET;
155 otherAddress.sin_port = htons(remotePartTCPPort);
160 remotePartAddress, solved_IP, DNS_LOOKUP_TIMEOUT_MS))
162 "DNS lookup failed for '%s'", remotePartAddress.c_str());
165 otherAddress.sin_addr.s_addr = inet_addr(solved_IP.c_str());
166 if (INADDR_NONE == otherAddress.sin_addr.s_addr)
168 "Invalid IP address provided: %s", solved_IP.c_str());
172 unsigned long non_block_mode = 1;
173 if (ioctlsocket(m_hSock, FIONBIO, &non_block_mode))
174 THROW_EXCEPTION(
"Error entering non-blocking mode with ioctlsocket();");
176 int oldflags = fcntl(m_hSock, F_GETFL, 0);
177 if (oldflags == -1)
THROW_EXCEPTION(
"Error retrieving fcntl();of socket.");
178 oldflags |= O_NONBLOCK;
179 if (-1 == fcntl(m_hSock, F_SETFL, oldflags))
185 m_hSock, (
struct sockaddr*)&otherAddress,
sizeof(otherAddress));
187 int er = WSAGetLastError();
188 if (
r < 0 && er != WSAEINPROGRESS && er != WSAEWOULDBLOCK)
191 if (
r < 0 && er != EINPROGRESS)
194 "Error connecting to %s:%hu. Error: %s [%d]",
195 remotePartAddress.c_str(), remotePartTCPPort, strerror(er), er));
201 FD_ZERO(&socket_set);
202 FD_SET(m_hSock, &socket_set);
204 timer.tv_sec = timeout_ms / 1000;
205 timer.tv_usec = 1000 * (timeout_ms % 1000);
207 int sel_ret = select(
212 timeout_ms == 0 ?
nullptr : &timer);
216 "Timeout connecting to '%s:%hu':\n%s", remotePartAddress.c_str(),
217 remotePartTCPPort, getLastErrorStr().c_str()));
220 "Error connecting to '%s:%hu':\n%s", remotePartAddress.c_str(),
221 remotePartTCPPort, getLastErrorStr().c_str()));
226 int lon =
sizeof(int);
227 getsockopt(m_hSock, SOL_SOCKET, SO_ERROR, (
char*)(&valopt), &
lon);
230 getsockopt(m_hSock, SOL_SOCKET, SO_ERROR, (
void*)(&valopt), &
lon);
236 "Error connecting to %s:%hu. Error: %i.", remotePartAddress.c_str(),
237 remotePartTCPPort, valopt));
241 "Error connecting to %s:%hu. Error: %s.", remotePartAddress.c_str(),
242 remotePartTCPPort, strerror(valopt)));
249 if (ioctlsocket(m_hSock, FIONBIO, &non_block_mode))
252 oldflags &= ~O_NONBLOCK;
253 if (-1 == fcntl(m_hSock, F_SETFL, oldflags))
258 m_remotePartIP = remotePartAddress;
271 void* Buffer,
const size_t Count,
const int timeoutStart_ms,
272 const int timeoutBetween_ms)
276 if (m_hSock == INVALID_SOCKET)
return 0;
278 size_t remainToRead, alreadyRead = 0;
280 bool timeoutExpired =
false;
282 struct timeval timeoutSelect;
283 struct timeval* ptrTimeout;
288 FD_SET(m_hSock, &sockArr);
291 while (alreadyRead < Count && !timeoutExpired)
294 int curTimeout = alreadyRead == 0 ? timeoutStart_ms : timeoutBetween_ms;
297 ptrTimeout =
nullptr;
300 timeoutSelect.tv_sec = curTimeout / 1000;
301 timeoutSelect.tv_usec = 1000 * (curTimeout % 1000);
302 ptrTimeout = &timeoutSelect;
306 int selRet = ::select(
313 if (selRet == INVALID_SOCKET)
315 "Error reading from socket: %s", getLastErrorStr().c_str());
320 timeoutExpired =
true;
325 remainToRead = Count - alreadyRead;
329 m_hSock, ((
char*)Buffer) + alreadyRead, (
int)remainToRead, 0);
331 if (readNow != INVALID_SOCKET)
334 alreadyRead += readNow;
343 if (readNow == 0 && remainToRead != 0)
347 timeoutExpired =
true;
362 const void* Buffer,
const size_t Count,
const int timeout_ms)
366 if (m_hSock == INVALID_SOCKET)
return 0;
368 size_t remainToWrite, alreadyWritten = 0;
370 bool timeoutExpired =
false;
372 struct timeval timeoutSelect;
373 struct timeval* ptrTimeout;
378 FD_SET(m_hSock, &sockArr);
383 ptrTimeout =
nullptr;
387 timeoutSelect.tv_sec = timeout_ms / 1000;
388 timeoutSelect.tv_usec = 1000 * (timeout_ms % 1000);
389 ptrTimeout = &timeoutSelect;
393 while (alreadyWritten < Count && !timeoutExpired)
396 int selRet = ::select(
403 if (selRet == INVALID_SOCKET)
405 "Error writing to socket: %s", getLastErrorStr().c_str());
410 timeoutExpired =
true;
417 remainToWrite = Count - alreadyWritten;
421 m_hSock, ((
char*)Buffer) + alreadyWritten, (
int)remainToWrite,
424 if (writtenNow != INVALID_SOCKET)
427 alreadyWritten += writtenNow;
433 return alreadyWritten;
443 if (m_hSock == INVALID_SOCKET)
return 0;
444 unsigned long ret = 0;
447 ioctlsocket(m_hSock, FIONREAD, &ret)
449 ioctl(m_hSock, FIONREAD, &ret)
464 int length =
sizeof(newValue);
467 m_hSock, IPPROTO_TCP, TCP_NODELAY, (
char*)&newValue,
length);
482 getsockopt(m_hSock, IPPROTO_TCP, TCP_NODELAY, (
char*)&
value, &
length);
495 const unsigned int length =
sizeof(newValue);
497 return setsockopt(m_hSock, SOL_SOCKET, SO_SNDBUF, (
char*)&newValue,
length);
511 getsockopt(m_hSock, SOL_SOCKET, SO_SNDBUF, (
char*)&
value, &
length);
static unsigned int DNS_LOOKUP_TIMEOUT_MS
See description of CClientTCPSocket.
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)
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 setSOSendBufffer(const int &newValue)
Set the size of the SO send buffer.
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.
GLsizei const GLchar ** string
std::string getLastErrorStr()
Returns a description of the last Sockets error.
unsigned __int64 uint64_t
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.
GLdouble GLdouble GLdouble r
uint64_t getPosition() const override
This virtual method has no effect in this implementation over a TCP socket, and its use raises an exc...
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
int setTCPNoDelay(const int &newValue)
Set the TCP no delay option of the protocol (Nagle algorithm).
GLuint GLsizei GLsizei * length
void close()
Closes the connection.
GLsizei const GLfloat * value
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.
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.