void PerfSocket::SetSocketOptions( void ) { // set the TCP window size (socket buffer sizes) // also the UDP buffer size // must occur before call to accept() for large window sizes set_tcp_windowsize( mSock, mSettings->mTCPWin ); #ifdef IP_TOS // set IP TOS (type-of-service) field if ( mSettings->mTOS > 0 ) { int tos = mSettings->mTOS; Socklen_t len = sizeof(tos); int rc = setsockopt( mSock, IPPROTO_IP, IP_TOS, (char*) &tos, len ); FAIL_errno( rc == SOCKET_ERROR, "setsockopt IP_TOS" ); } #endif if ( ! mUDP ) { // set the TCP maximum segment size if(mSettings->mProtocol != IPPROTO_SCTP) { setsock_tcp_mss( mSock, mSettings->mMSS ); #ifdef TCP_NODELAY // set TCP nodelay option if ( mSettings->mNodelay ) { int nodelay = 1; Socklen_t len = sizeof(nodelay); int rc = setsockopt( mSock, IPPROTO_TCP, TCP_NODELAY, (char*) &nodelay, len ); FAIL_errno( rc == SOCKET_ERROR, "setsockopt TCP_NODELAY" ); } #endif } else { mSettings->mMSS = getsock_sctp_mss( mSock ); #ifdef SCTP_NODELAY // set TCP nodelay option if ( mSettings->mNodelay ) { int nodelay = 1; Socklen_t len = sizeof(nodelay); int rc = setsockopt( mSock, IPPROTO_SCTP, SCTP_NODELAY, (char*) &nodelay, len ); FAIL_errno( rc == SOCKET_ERROR, "setsockopt SCTP_NODELAY" ); } #endif #if defined(SCTP_PARTIAL_DELIVERY_POINT) && defined(SCTP_EXPLICIT_EOR) if(mSettings->mEmulation == true) { int rc; int val=1; Socklen_t len = sizeof(int); rc = setsockopt( mSock, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT, (char*) &val, len ); FAIL_errno( rc == SOCKET_ERROR, "setsockopt SCTP_PARTIAL_DELIVERY_POINT" ); rc = setsockopt( mSock, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, (char*) &val, len ); FAIL_errno( rc == SOCKET_ERROR, "setsockopt SCTP_EXPLICT_EOR" ); } #endif } } }
void PerfSocket::Client_Recv_TCP(void) { // terminate loop nicely on user interupts sInterupted = false; //my_signal( SIGINT, Sig_Interupt ); //my_signal( SIGPIPE, Sig_Interupt ); #ifndef WIN32 signal (SIGPIPE, SIG_IGN); #endif int currLen; InitTransfer(); double fract = 0.0; mStartTime.setnow(); long endSize = get_tcp_windowsize(mSock), startSize=endSize, loopLen =0, prevLen =0; Timestamp prevTime; prevTime.setnow(); /* Periodic reporting is done here in the loop itself, if Suggest Window Size option is set*/ mPReporting = false; /* Send the first packet indicating that the server has to send data */ mBuf[0] = 'a'; currLen = write( mSock, mBuf, mSettings->mBufLen ); if ( currLen < 0 ) { WARN_errno( currLen < 0, "write" ); return; } do { // perform read currLen = read( mSock, mBuf, mSettings->mBufLen ); mPacketTime.setnow(); if ( currLen < 0 ) { WARN_errno( currLen < 0, "read" ); break; } mTotalLen += currLen; loopLen +=currLen; // periodically report bandwidths ReportPeriodicBW(); double nFract = mStartTime.fraction(mPacketTime,mEndTime); if ( nFract > (fract + 0.1) ) { printf(seperator_line); ReportWindowSize(); sReporting.Lock(); ReportBW( loopLen, prevTime.subSec(mStartTime), mPacketTime.subSec( mStartTime)); sReporting.Unlock(); fract +=0.1; if ( startSize != endSize ) { /* Change the window size only if the data transfer has changed at least by 5% */ if ( loopLen < prevLen ) { if ( ( ((double)(prevLen - loopLen)) / ((double)prevLen)) > 0.05 ) { endSize = startSize + (endSize - startSize)/2; } } else { if ( ( ((double)(loopLen - prevLen)) / ((double)prevLen) ) > 0.05 ) { startSize = endSize; endSize = endSize*2; prevLen = loopLen; } } } else { endSize = endSize*2; prevLen = loopLen; } /** Reset the variables after setting new window size */ prevTime.setnow(); loopLen = 0 ; //shutdown(mSock,SHUT_RDWR); close(mSock); mSock = -1; Connect( mSettings->mHost, mSettings->mLocalhost ); mBuf[0] = 'a'; if ( set_tcp_windowsize(mSock,endSize) == -1 ) { printf(unable_to_change_win); } if ( get_tcp_windowsize(mSock) != endSize ) { printf(unable_to_change_win); } write( mSock, mBuf, mSettings->mBufLen ); } } while ( ! (sInterupted || (mMode_time && mPacketTime.after( mEndTime )) || (!mMode_time && mTotalLen >= mAmount)) ); printf( seperator_line ); ReportWindowSize(); sReporting.Lock(); ReportBW( loopLen, prevTime.subSec(mStartTime), mPacketTime.subSec( mStartTime)); sReporting.Unlock(); printf( seperator_line); printf( opt_estimate); if ( loopLen > prevLen ) set_tcp_windowsize(mSock,endSize); else set_tcp_windowsize(mSock,startSize); ReportWindowSize(); printf( seperator_line ); // stop timing mEndTime.setnow(); sReporting.Lock(); ReportBW( mTotalLen, 0.0, mEndTime.subSec( mStartTime )); sReporting.Unlock(); if ( mSettings->mPrintMSS ) { // read the socket option for MSS (maximum segment size) ReportMSS( getsock_tcp_mss( mSock )); } //close(mSock); //mSock = -1; }