18 #ifdef MRPT_OS_WINDOWS 20 #define _WINSOCK_DEPRECATED_NO_WARNINGS 23 #if defined(__BORLANDC__) || defined(_MSC_VER) 24 #pragma comment (lib,"WS2_32.LIB") 28 #define INVALID_SOCKET (-1) 29 #include <sys/socket.h> 33 #include <sys/types.h> 34 #include <sys/ioctl.h> 36 #include <arpa/inet.h> 37 #include <netinet/in.h> 38 #include <netinet/tcp.h> 53 #ifdef MRPT_OS_WINDOWS 56 WORD wVersionRequested;
59 wVersionRequested = MAKEWORD( 2, 0 );
61 if (WSAStartup( wVersionRequested, &wsaData ) )
76 #ifdef MRPT_OS_WINDOWS 87 #ifdef MRPT_OS_WINDOWS 91 shutdown(m_hSock, 2 );
92 closesocket( m_hSock );
99 shutdown(m_hSock, SHUT_RDWR );
116 return readAsync(Buffer,Count);
128 return writeAsync(Buffer,Count);
138 Write( str.c_str(), str.size() );
149 uint32_t contentLen, toWrite,written;
154 const char *magic=
"MRPTMessage";
155 toWrite = strlen(magic);
157 written = writeAsync( magic, toWrite, timeout_ms );
158 if (written!=toWrite)
return false;
163 toWrite =
sizeof( outMsg.
type );
165 written = writeAsync( &outMsg.
type, toWrite, timeout_ms );
166 if (written!=toWrite)
return false;
171 contentLen = outMsg.
content.size();
172 toWrite =
sizeof( contentLen );
174 written = writeAsync( &contentLen, toWrite, timeout_ms );
175 if (written!=toWrite)
return false;
180 toWrite = contentLen;
182 written = writeAsync( &outMsg.
content[0], toWrite, timeout_ms );
183 if (written!=toWrite)
return false;
193 unsigned int timeoutStart_ms,
194 unsigned int timeoutBetween_ms
197 uint32_t contentLen, toRead,actRead;
205 actRead = readAsync( magic,toRead,timeoutStart_ms,timeoutBetween_ms );
206 if (actRead!=toRead)
return false;
216 toRead =
sizeof( inMsg.
type );
218 actRead = readAsync( &inMsg.
type,toRead,timeoutBetween_ms,timeoutBetween_ms );
219 if (actRead!=toRead)
return false;
224 toRead =
sizeof( contentLen );
226 actRead = readAsync( &contentLen,toRead,timeoutBetween_ms,timeoutBetween_ms );
227 if (actRead!=toRead)
return false;
230 inMsg.
content.resize( contentLen );
237 actRead = readAsync( &inMsg.
content[0],toRead,timeoutBetween_ms,timeoutBetween_ms);
238 if (actRead!=toRead)
return false;
250 unsigned short remotePartTCPPort,
251 unsigned int timeout_ms )
260 if (
INVALID_SOCKET == (m_hSock = socket(AF_INET, SOCK_STREAM, 0)) )
263 struct sockaddr_in otherAddress;
265 otherAddress.sin_family = AF_INET;
266 otherAddress.sin_port = htons(remotePartTCPPort);
275 otherAddress.sin_addr.s_addr = inet_addr(solved_IP.c_str());
276 if (INADDR_NONE==otherAddress.sin_addr.s_addr)
280 #ifdef MRPT_OS_WINDOWS 281 unsigned long non_block_mode = 1;
282 if (ioctlsocket(m_hSock, FIONBIO, &non_block_mode) )
THROW_EXCEPTION(
"Error entering non-blocking mode with ioctlsocket()." );
284 int oldflags=fcntl(m_hSock, F_GETFL, 0);
285 if (oldflags == -1)
THROW_EXCEPTION(
"Error retrieving fcntl() of socket." );
286 oldflags |= O_NONBLOCK;
287 if (-1==fcntl(m_hSock, F_SETFL, oldflags))
THROW_EXCEPTION(
"Error entering non-blocking mode with fcntl()." );
291 int r = ::connect( m_hSock , (
struct sockaddr *)&otherAddress,
sizeof(otherAddress));
292 #ifdef MRPT_OS_WINDOWS 293 int er = WSAGetLastError();
294 if (
r < 0 && er != WSAEINPROGRESS && er != WSAEWOULDBLOCK)
297 if (
r < 0 && er != EINPROGRESS)
299 THROW_EXCEPTION(
format(
"Error connecting to %s:%hu. Error: %s [%d]", remotePartAddress.c_str(), remotePartTCPPort, strerror(er),er));
305 FD_ZERO(&socket_set);
306 FD_SET(m_hSock,&socket_set);
308 timer.tv_sec = timeout_ms/1000;
309 timer.tv_usec = 1000*(timeout_ms%1000);
311 int sel_ret = select(
316 timeout_ms==0 ? NULL : &timer
319 if (sel_ret == 0)
THROW_EXCEPTION(
format(
"Timeout connecting to '%s:%hu':\n%s",remotePartAddress.c_str(),remotePartTCPPort, getLastErrorStr().c_str() ));
320 if (sel_ret ==-1)
THROW_EXCEPTION(
format(
"Error connecting to '%s:%hu':\n%s",remotePartAddress.c_str(),remotePartTCPPort, getLastErrorStr().c_str() ));
324 #ifdef MRPT_OS_WINDOWS 325 int lon =
sizeof(int);
326 getsockopt(m_hSock, SOL_SOCKET, SO_ERROR, (
char*)(&valopt), &
lon);
328 socklen_t
lon =
sizeof(int);
329 getsockopt(m_hSock, SOL_SOCKET, SO_ERROR, (
void*)(&valopt), &
lon);
332 #ifdef MRPT_OS_WINDOWS 333 if (valopt)
THROW_EXCEPTION(
format(
"Error connecting to %s:%hu. Error: %i.", remotePartAddress.c_str(), remotePartTCPPort, valopt));
335 if (valopt)
THROW_EXCEPTION(
format(
"Error connecting to %s:%hu. Error: %s.", remotePartAddress.c_str(), remotePartTCPPort, strerror(valopt)));
340 #ifdef MRPT_OS_WINDOWS 342 if (ioctlsocket(m_hSock, FIONBIO, &non_block_mode) )
THROW_EXCEPTION(
"Error entering blocking mode with ioctlsocket()." );
344 oldflags &= ~O_NONBLOCK;
345 if (-1==fcntl(m_hSock, F_SETFL, oldflags))
THROW_EXCEPTION(
"Error entering blocking mode with fcntl()." );
349 m_remotePartIP = remotePartAddress;
370 const int timeoutStart_ms,
371 const int timeoutBetween_ms )
377 size_t remainToRead, alreadyRead = 0;
379 bool timeoutExpired =
false;
381 struct timeval timeoutSelect;
382 struct timeval *ptrTimeout;
387 FD_SET(m_hSock, &sockArr);
390 while ( alreadyRead<Count && !timeoutExpired )
393 int curTimeout = alreadyRead==0 ? timeoutStart_ms : timeoutBetween_ms;
399 timeoutSelect.tv_sec = curTimeout / 1000;
400 timeoutSelect.tv_usec = 1000 * (curTimeout % 1000);
401 ptrTimeout = &timeoutSelect;
405 int selRet = ::select(
418 timeoutExpired =
true;
423 remainToRead = Count - alreadyRead;
426 readNow = ::recv( m_hSock, ((
char*)Buffer) + alreadyRead, (
int)remainToRead, 0);
431 alreadyRead += readNow;
440 if (readNow==0 && remainToRead!=0)
444 timeoutExpired =
true;
461 const int timeout_ms )
467 size_t remainToWrite, alreadyWritten = 0;
469 bool timeoutExpired =
false;
471 struct timeval timeoutSelect;
472 struct timeval *ptrTimeout;
477 FD_SET(m_hSock, &sockArr);
486 timeoutSelect.tv_sec = timeout_ms / 1000;
487 timeoutSelect.tv_usec = 1000 * (timeout_ms % 1000);
488 ptrTimeout = &timeoutSelect;
492 while ( alreadyWritten<Count && !timeoutExpired )
495 int selRet = ::select(
508 timeoutExpired =
true;
515 remainToWrite = Count - alreadyWritten;
518 writtenNow = ::send( m_hSock, ((
char*)Buffer) + alreadyWritten, (
int)remainToWrite, 0);
523 alreadyWritten += writtenNow;
529 return alreadyWritten;
544 #ifdef MRPT_OS_WINDOWS
545 ioctlsocket(m_hSock,FIONREAD,&ret)
547 ioctl(m_hSock, FIONREAD, &ret)
562 int length =
sizeof( newValue );
564 return setsockopt(m_hSock,IPPROTO_TCP,TCP_NODELAY,(
char*)&newValue,
length);
574 #ifdef MRPT_OS_WINDOWS 579 int res = getsockopt(m_hSock, IPPROTO_TCP, TCP_NODELAY, (
char*)&
value, &
length );
592 const unsigned int length =
sizeof( newValue );
594 return setsockopt(m_hSock, SOL_SOCKET, SO_SNDBUF, (
char*)&newValue,
length );
604 #ifdef MRPT_OS_WINDOWS 609 getsockopt(m_hSock, SOL_SOCKET, SO_SNDBUF, (
char*)&
value, &
length );
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
~CClientTCPSocket()
Destructor.
This namespace provides a OS-independent interface to many useful functions: filenames manipulation...
#define THROW_EXCEPTION(msg)
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
void sendString(const std::string &str)
Writes a string to the socket.
size_t Read(void *Buffer, size_t Count) MRPT_OVERRIDE
Introduces a virtual method responsible for reading from the stream (This method BLOCKS) This method ...
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.
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.
void close()
Closes the connection.
bool sendMessage(const CMessage &outMsg, const int timeout_ms=-1)
Send a message through the TCP stream.
bool isConnected()
Returns true if this objects represents a successfully connected socket.
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
static unsigned int DNS_LOOKUP_TIMEOUT_MS
See description of CClientTCPSocket.
int setSOSendBufffer(const int &newValue)
Set the size of the SO send buffer.
GLsizei const GLchar ** string
size_t Write(const void *Buffer, size_t Count) MRPT_OVERRIDE
Introduces a virtual method responsible for writing to the stream.
int getSOSendBufffer()
Return the current size of the SO send buffer.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void connect(const std::string &remotePartAddress, unsigned short remotePartTCPPort, unsigned int timeout_ms=0)
Establishes a connection with a remote part.
GLdouble GLdouble GLdouble r
CClientTCPSocket()
Default constructor.
size_t getReadPendingBytes()
Return the number of bytes already in the receive queue (they can be read without waiting) ...
int BASE_IMPEXP _strcmpi(const char *str1, const char *str2) MRPT_NO_THROWS
An OS-independent version of strcmpi.
int getTCPNoDelay()
Return the value of the TCPNoDelay option.
GLuint GLsizei GLsizei * length
bool BASE_IMPEXP 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...
std::vector< uint8_t > content
The contents of the message (memory is automatically handled by the std::vector object) ...
GLsizei const GLfloat * value
bool receiveMessage(CMessage &inMsg, const unsigned int timeoutStart_ms=100, const unsigned int timeoutBetween_ms=1000)
Waits for an incoming message through the TCP stream.
unsigned __int32 uint32_t
A class that contain generic messages, that can be sent and received from a "CClientTCPSocket" object...
uint32_t type
An identifier of the message type (only the least-sig byte is typically sent)
int setTCPNoDelay(const int &newValue)
Set the TCP no delay option of the protocol (Nagle algorithm).