|
From: <gb...@us...> - 2008-10-15 09:10:32
|
Revision: 323
http://gearbox.svn.sourceforge.net/gearbox/?rev=323&view=rev
Author: gbiggs
Date: 2008-10-15 09:10:21 +0000 (Wed, 15 Oct 2008)
Log Message:
-----------
Added support for ReadUntil and ReadLine (char* version) to UDPPort.
Modified Paths:
--------------
gearbox/trunk/src/flexiport/tcpport.cpp
gearbox/trunk/src/flexiport/test/udp_example.cpp
gearbox/trunk/src/flexiport/udpport.cpp
gearbox/trunk/src/flexiport/udpport.h
Modified: gearbox/trunk/src/flexiport/tcpport.cpp
===================================================================
--- gearbox/trunk/src/flexiport/tcpport.cpp 2008-10-15 07:03:32 UTC (rev 322)
+++ gearbox/trunk/src/flexiport/tcpport.cpp 2008-10-15 09:10:21 UTC (rev 323)
@@ -296,10 +296,10 @@
{
#if defined (WIN32)
numReceived = recv (_sock, &(reinterpret_cast<char*> (buffer)[receivedBytes]),
- count, 0); // No MSG_WAITALL on older versions of visual c, it seems
+ count - receivedBytes, 0); // No MSG_WAITALL on older versions of visual c, it seems
#else
numReceived = recv (_sock, &(reinterpret_cast<char*> (buffer)[receivedBytes]),
- count, MSG_WAITALL);
+ count - receivedBytes, MSG_WAITALL);
#endif
if (_debug >= 2)
cerr << "TCPPort::" << __func__ << "() Received " << numReceived << " bytes" << endl;
Modified: gearbox/trunk/src/flexiport/test/udp_example.cpp
===================================================================
--- gearbox/trunk/src/flexiport/test/udp_example.cpp 2008-10-15 07:03:32 UTC (rev 322)
+++ gearbox/trunk/src/flexiport/test/udp_example.cpp 2008-10-15 09:10:21 UTC (rev 323)
@@ -81,6 +81,10 @@
SLEEP (5);
cout << "Client sending 'Probably message #3.'" << endl;
port->WriteString ("Probably message #3.");
+ SLEEP (5);
+ cout << "Client sending 'Probably message #4\\n'" << endl;
+ char charMessage2[] = "Probably message #4\n";
+ port->Write (charMessage2, strlen (charMessage2) + 1);
cout << "Client waiting for parting message." << endl;
port->ReadString (stringMessage);
cout << "Client got parting message: \"" << stringMessage << '"' << endl;
@@ -131,6 +135,15 @@
cout << "Test failed." << endl;
return -1;
}
+ cout << "Server testing ReadUntil()" << endl;
+ int bytesReceived;
+ bytesReceived = port->ReadUntil (charBuffer, 32, 'e');
+ cout << "Server received \"" << charBuffer << "\" (" << bytesReceived << " bytes)" << endl;
+ if (strncmp (charBuffer, "Probably message #4\n", 20) != 0)
+ {
+ cout << "Test failed." << endl;
+ return -1;
+ }
cout << "Server sending back to client" << endl;
port->WriteString ("So long, and thanks for all the text.");
SLEEP (5);
Modified: gearbox/trunk/src/flexiport/udpport.cpp
===================================================================
--- gearbox/trunk/src/flexiport/udpport.cpp 2008-10-15 07:03:32 UTC (rev 322)
+++ gearbox/trunk/src/flexiport/udpport.cpp 2008-10-15 09:10:21 UTC (rev 323)
@@ -262,10 +262,10 @@
{
#if defined (WIN32)
numReceived = recv (_recvSock, &(reinterpret_cast<char*> (buffer)[receivedBytes]),
- count, 0); // No MSG_WAITALL on older versions of visual c, it seems
+ count - receivedBytes, 0); // No MSG_WAITALL on older versions of visual c, it seems
#else
numReceived = recv (_recvSock, &(reinterpret_cast<char*> (buffer)[receivedBytes]),
- count, MSG_WAITALL);
+ count - receivedBytes, MSG_WAITALL);
#endif
if (_debug >= 2)
cerr << "UDPPort::" << __func__ << "() Received " << numReceived << " bytes" << endl;
@@ -314,36 +314,86 @@
ssize_t UDPPort::ReadUntil (void * const buffer, size_t count, uint8_t terminator)
{
- throw PortException (string ("UDPPort::") + __func__ +
- string ("() This function does not work for datagram-oriented protocols."));
- return 0;
+ // For a datagram protocol, any read will remove the entire datagram from the socket buffer, no
+ // matter how much we actually ask for (although we will still get the amount we asked for in
+ // out buffer). This means we cannot read 1 byte at a time, because we would only get the first
+ // byte of each datagram. However, since reading any of a datagram removes the whole lot, we
+ // can just keep reading as much as possible until we see the terminator somewhere in a received
+ // chunk of data.
+ // This will be fixed if static buffers are introduced.
+
+ size_t numRead = 0;
+
+ CheckPort (true);
+
+ if (_debug >= 2)
+ {
+ cerr << "UDPPort::" << __func__ << "() Reading until '" << terminator << "' or " <<
+ count << " bytes." << endl;
+ }
+ while (numRead < count)
+ {
+ ssize_t result = 0;
+ if ((result = Read (reinterpret_cast<void*> (&reinterpret_cast<char*> (buffer)[numRead]), count - numRead)) < 0)
+ return -1; // Timeout
+ else if (result == 0)
+ {
+ // No data received and didn't timeout, so must be in non-blocking mode
+ if (IsBlocking ())
+ cerr << "UDPPort::" << __func__ << "() Got no data when in blocking mode." << endl;
+ return 0;
+ }
+ else
+ {
+ // Got data
+ if (_debug >= 2)
+ cerr << "UDPPort::" << __func__ << "() Read " << result << " bytes." << endl;
+ // Go through the data just received and check if any bytes match the terminator
+ bool foundTerminator = false;
+ // numKeep starts at 1 because we will keep at least one byte if the first is terminal
+ size_t numKeep = 1;
+ for (size_t ii = numRead; ii < numRead + result; ii++, numKeep++)
+ {
+ if (reinterpret_cast<uint8_t*>(buffer)[ii] == terminator)
+ {
+ if (_debug >= 2)
+ cerr << "UDPPort::" << __func__ << "() Got terminator character." << endl;
+ foundTerminator = true;
+ // We don't care about any data passed this point - as far as the application
+ // knows, it's as much garbage as real data, so don't waste time clearing it
+ break;
+ }
+ }
+ numRead += numKeep;
+ if (foundTerminator)
+ {
+ // Got the terminator so stop reading now
+ break;
+ }
+ }
+ }
+
+ return numRead;
}
ssize_t UDPPort::ReadStringUntil (std::string &buffer, char terminator)
{
throw PortException (string ("UDPPort::") + __func__ +
- string ("() This function does not work for datagram-oriented protocols."));
+ string ("() This function does not work for datagram protocols."));
return 0;
}
-ssize_t UDPPort::ReadLine (char * const buffer, size_t count)
-{
- throw PortException (string ("UDPPort::") + __func__ +
- string ("() This function does not work for datagram-oriented protocols."));
- return 0;
-}
-
ssize_t UDPPort::Skip (size_t count)
{
throw PortException (string ("UDPPort::") + __func__ +
- string ("() This function does not work for datagram-oriented protocols."));
+ string ("() This function does not work for datagram protocols."));
return 0;
}
ssize_t UDPPort::SkipUntil (uint8_t terminator, unsigned int count)
{
throw PortException (string ("UDPPort::") + __func__ +
- string ("() This function does not work for datagram-oriented protocols."));
+ string ("() This function does not work for datagram protocols."));
return 0;
}
Modified: gearbox/trunk/src/flexiport/udpport.h
===================================================================
--- gearbox/trunk/src/flexiport/udpport.h 2008-10-15 07:03:32 UTC (rev 322)
+++ gearbox/trunk/src/flexiport/udpport.h 2008-10-15 09:10:21 UTC (rev 323)
@@ -46,8 +46,8 @@
See the @ref Port class documentation for how to use the common API. Note that some parts of the API
do not apply due to the nature of the datagram-oriented protocol. Because each datagram is
individual and no merging is typically performed between datagrams, several flexiport functions do
-not work (they were designed for stream-oriented communications). These are @ref ReadUntil,
-@ref ReadStringUntil, @ref ReadLine, @ref Skip, and @ref SkipUntil. This will be (hopefully) be
+not work (they were designed for stream-oriented communications). These are @ref ReadStringUntil,
+@ref ReadLine (std::string version), @ref Skip, and @ref SkipUntil. This will be (hopefully) be
fixed soon.
TODO: Add support for configuring the destination address based on the first data received, to allow
@@ -90,8 +90,6 @@
ssize_t ReadUntil (void * const buffer, size_t count, uint8_t terminator);
/// @brief Read a string until the specified termination character is received.
ssize_t ReadStringUntil (std::string &buffer, char terminator);
- /// @brief Read a new-line terminated string of data.
- ssize_t ReadLine (char * const buffer, size_t count);
/// @brief Dump data until the specified number of bytes have been read.
ssize_t Skip (size_t count);
/** @brief Read and dump data until the specified termination character has been seen @ref
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|