19 #define _WINSOCK_DEPRECATED_NO_WARNINGS 23 #pragma comment(lib, "WS2_32.LIB") 27 #define INVALID_SOCKET (-1) 28 #include <sys/socket.h> 32 #include <sys/types.h> 33 #include <sys/ioctl.h> 35 #include <arpa/inet.h> 36 #include <netinet/in.h> 37 #include <netinet/tcp.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)))
150 "Error creating new client socket:\n%s",
151 getLastErrorStr().c_str()));
153 struct sockaddr_in otherAddress;
155 otherAddress.sin_family = AF_INET;
156 otherAddress.sin_port = htons(remotePartTCPPort);
161 remotePartAddress, solved_IP, DNS_LOOKUP_TIMEOUT_MS))
163 "DNS lookup failed for '%s'", remotePartAddress.c_str());
166 otherAddress.sin_addr.s_addr = inet_addr(solved_IP.c_str());
167 if (INADDR_NONE == otherAddress.sin_addr.s_addr)
169 "Invalid IP address provided: %s", solved_IP.c_str());
173 unsigned long non_block_mode = 1;
174 if (ioctlsocket(m_hSock, FIONBIO, &non_block_mode))
175 THROW_EXCEPTION(
"Error entering non-blocking mode with ioctlsocket();");
177 int oldflags = fcntl(m_hSock, F_GETFL, 0);
178 if (oldflags == -1)
THROW_EXCEPTION(
"Error retrieving fcntl();of socket.");
179 oldflags |= O_NONBLOCK;
180 if (-1 == fcntl(m_hSock, F_SETFL, oldflags))
186 m_hSock, (
struct sockaddr*)&otherAddress,
sizeof(otherAddress));
188 int er = WSAGetLastError();
189 if (
r < 0 && er != WSAEINPROGRESS && er != WSAEWOULDBLOCK)
192 if (
r < 0 && er != EINPROGRESS)
196 "Error connecting to %s:%hu. Error: %s [%d]",
197 remotePartAddress.c_str(), remotePartTCPPort, strerror(er),
204 FD_ZERO(&socket_set);
205 FD_SET(m_hSock, &socket_set);
207 timer.tv_sec = timeout_ms / 1000;
208 timer.tv_usec = 1000 * (timeout_ms % 1000);
210 int sel_ret = select(
215 timeout_ms == 0 ?
nullptr : &timer);
220 "Timeout connecting to '%s:%hu':\n%s",
221 remotePartAddress.c_str(), remotePartTCPPort,
222 getLastErrorStr().c_str()));
226 "Error connecting to '%s:%hu':\n%s", remotePartAddress.c_str(),
227 remotePartTCPPort, getLastErrorStr().c_str()));
232 int lon =
sizeof(int);
233 getsockopt(m_hSock, SOL_SOCKET, SO_ERROR, (
char*)(&valopt), &
lon);
236 getsockopt(m_hSock, SOL_SOCKET, SO_ERROR, (
void*)(&valopt), &
lon);
243 "Error connecting to %s:%hu. Error: %i.",
244 remotePartAddress.c_str(), remotePartTCPPort, valopt));
249 "Error connecting to %s:%hu. Error: %s.",
250 remotePartAddress.c_str(), remotePartTCPPort,
258 if (ioctlsocket(m_hSock, FIONBIO, &non_block_mode))
261 oldflags &= ~O_NONBLOCK;
262 if (-1 == fcntl(m_hSock, F_SETFL, oldflags))
267 m_remotePartIP = remotePartAddress;
280 void* Buffer,
const size_t Count,
const int timeoutStart_ms,
281 const int timeoutBetween_ms)
285 if (m_hSock == INVALID_SOCKET)
return 0;
287 size_t remainToRead, alreadyRead = 0;
289 bool timeoutExpired =
false;
291 struct timeval timeoutSelect;
292 struct timeval* ptrTimeout;
297 FD_SET(m_hSock, &sockArr);
300 while (alreadyRead < Count && !timeoutExpired)
303 int curTimeout = alreadyRead == 0 ? timeoutStart_ms : timeoutBetween_ms;
306 ptrTimeout =
nullptr;
309 timeoutSelect.tv_sec = curTimeout / 1000;
310 timeoutSelect.tv_usec = 1000 * (curTimeout % 1000);
311 ptrTimeout = &timeoutSelect;
315 int selRet = ::select(
322 if (selRet == INVALID_SOCKET)
324 "Error reading from socket: %s", getLastErrorStr().c_str());
329 timeoutExpired =
true;
334 remainToRead = Count - alreadyRead;
338 m_hSock, ((
char*)Buffer) + alreadyRead, (
int)remainToRead, 0);
340 if (readNow != INVALID_SOCKET)
343 alreadyRead += readNow;
352 if (readNow == 0 && remainToRead != 0)
356 timeoutExpired =
true;
371 const void* Buffer,
const size_t Count,
const int timeout_ms)
375 if (m_hSock == INVALID_SOCKET)
return 0;
377 size_t remainToWrite, alreadyWritten = 0;
379 bool timeoutExpired =
false;
381 struct timeval timeoutSelect;
382 struct timeval* ptrTimeout;
387 FD_SET(m_hSock, &sockArr);
392 ptrTimeout =
nullptr;
396 timeoutSelect.tv_sec = timeout_ms / 1000;
397 timeoutSelect.tv_usec = 1000 * (timeout_ms % 1000);
398 ptrTimeout = &timeoutSelect;
402 while (alreadyWritten < Count && !timeoutExpired)
405 int selRet = ::select(
412 if (selRet == INVALID_SOCKET)
414 "Error writing to socket: %s", getLastErrorStr().c_str());
419 timeoutExpired =
true;
426 remainToWrite = Count - alreadyWritten;
430 m_hSock, ((
char*)Buffer) + alreadyWritten, (
int)remainToWrite,
433 if (writtenNow != INVALID_SOCKET)
436 alreadyWritten += writtenNow;
442 return alreadyWritten;
452 if (m_hSock == INVALID_SOCKET)
return 0;
453 unsigned long ret = 0;
456 ioctlsocket(m_hSock, FIONREAD, &ret)
458 ioctl(m_hSock, FIONREAD, &ret)
473 int length =
sizeof(newValue);
476 m_hSock, IPPROTO_TCP, TCP_NODELAY, (
char*)&newValue,
length);
491 getsockopt(m_hSock, IPPROTO_TCP, TCP_NODELAY, (
char*)&
value, &
length);
504 const unsigned int length =
sizeof(newValue);
506 return setsockopt(m_hSock, SOL_SOCKET, SO_SNDBUF, (
char*)&newValue,
length);
520 getsockopt(m_hSock, SOL_SOCKET, SO_SNDBUF, (
char*)&
value, &
length);
static unsigned int DNS_LOOKUP_TIMEOUT_MS
See description of CClientTCPSocket.
~CClientTCPSocket()
Destructor.
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...
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.