blob: 7e69c9593f9952ba38a1d337ce9ba7bed7b9bf28 [file] [log] [blame]
Set SO_LINGER on client sockets so that we don't stop timing a
transfer until the server has acked our data. Without this, we end up
stopping timing while data is still in flight and, if there's enough
data in flight, we overreport bandwidth.
diff --git a/include/Client.hpp b/include/Client.hpp
index 1309a00..e1ab11c 100644
--- a/include/Client.hpp
+++ b/include/Client.hpp
@@ -82,6 +82,9 @@ public:
// client connect
void Connect( );
+ // Closes underlying socket
+ void Close( );
+
protected:
thread_Settings *mSettings;
char* mBuf;
diff --git a/src/Client.cpp b/src/Client.cpp
index e0a6950..484a240 100644
--- a/src/Client.cpp
+++ b/src/Client.cpp
@@ -104,13 +104,18 @@ Client::Client( thread_Settings *inSettings ) {
* ------------------------------------------------------------------- */
Client::~Client() {
+ Close();
+ DELETE_ARRAY( mBuf );
+} // end ~Client
+
+void Client::Close() {
if ( mSettings->mSock != INVALID_SOCKET ) {
int rc = close( mSettings->mSock );
WARN_errno( rc == SOCKET_ERROR, "close" );
mSettings->mSock = INVALID_SOCKET;
}
- DELETE_ARRAY( mBuf );
-} // end ~Client
+}
+
const double kSecs_to_usecs = 1e6;
const int kBytes_to_Bits = 8;
@@ -176,6 +181,8 @@ void Client::RunTCP( void ) {
} while ( ! (sInterupted ||
(!mMode_Time && 0 >= mSettings->mAmount)) && canRead );
+ Close();
+
// stop timing
gettimeofday( &(reportstruct->packetTime), NULL );
@@ -193,7 +200,6 @@ void Client::RunTCP( void ) {
/* -------------------------------------------------------------------
* Send data using the connected UDP/TCP socket,
* until a termination flag is reached.
- * Does not close the socket.
* ------------------------------------------------------------------- */
void Client::Run( void ) {
@@ -316,7 +322,9 @@ void Client::Run( void ) {
} while ( ! (sInterupted ||
(mMode_Time && mEndTime.before( reportstruct->packetTime )) ||
(!mMode_Time && 0 >= mSettings->mAmount)) && canRead );
-
+ if (! isUDP( mSettings)) {
+ Close();
+ }
// stop timing
gettimeofday( &(reportstruct->packetTime), NULL );
CloseReport( mSettings->reporthdr, reportstruct );
@@ -422,6 +430,9 @@ void Client::write_UDP_FIN( ) {
fd_set readSet;
struct timeval timeout;
+ FAIL(mSettings->mSock == INVALID_SOCKET,
+ "Closed socket in write_UDP_FIN", mSettings);
+
int count = 0;
while ( count < 10 ) {
count++;
diff --git a/src/PerfSocket.cpp b/src/PerfSocket.cpp
index 3ecdbe0..0a9a27a 100644
--- a/src/PerfSocket.cpp
+++ b/src/PerfSocket.cpp
@@ -152,6 +152,19 @@ void SetSocketOptions( thread_Settings *inSettings ) {
(char*) &nodelay, len );
WARN_errno( rc == SOCKET_ERROR, "setsockopt TCP_NODELAY" );
}
+
+#ifdef SO_LINGER
+ {
+ // Set SO_LINGER so that we don't stop timing before the
+ // far end acks our data.
+ struct linger linger = {1, 360}; // { linger, seconds to linger for}
+ int rc = setsockopt(inSettings->mSock, SOL_SOCKET, SO_LINGER,
+ &linger, sizeof(linger));
+ WARN_errno( rc == SOCKET_ERROR, "setsockopt SO_LINGER");
+ }
+#endif // SO_LINGER
+
+
#endif
}
}