📄 client.cpp
字号:
/ mSettings->mUDPRate) ); if ( delay_target < 0 || delay_target > (int) 1 * kSecs_to_usecs ) { fprintf( stderr, warn_delay_large, delay_target / kSecs_to_usecs ); delay_target = (int) kSecs_to_usecs * 1; } if ( isFileInput( mSettings ) ) { if ( isCompat( mSettings ) ) { Extractor_reduceReadSize( sizeof(struct UDP_datagram), mSettings ); readAt += sizeof(struct UDP_datagram); } else { Extractor_reduceReadSize( sizeof(struct UDP_datagram) + sizeof(struct client_hdr), mSettings ); readAt += sizeof(struct UDP_datagram) + sizeof(struct client_hdr); } } } ReportStruct *reportstruct = NULL; // InitReport handles Barrier for multiple Streams mSettings->reporthdr = InitReport( mSettings ); reportstruct = new ReportStruct; reportstruct->packetID = 0; lastPacketTime.setnow(); do { // Test case: drop 17 packets and send 2 out-of-order: // sequence 51, 52, 70, 53, 54, 71, 72 //switch( datagramID ) { // case 53: datagramID = 70; break; // case 71: datagramID = 53; break; // case 55: datagramID = 71; break; // default: break; //} gettimeofday( &(reportstruct->packetTime), NULL ); if ( isUDP( mSettings ) ) { // store datagram ID into buffer mBuf_UDP->id = htonl( (reportstruct->packetID)++ ); mBuf_UDP->tv_sec = htonl( reportstruct->packetTime.tv_sec ); mBuf_UDP->tv_usec = htonl( reportstruct->packetTime.tv_usec ); // delay between writes // make an adjustment for how long the last loop iteration took // TODO this doesn't work well in certain cases, like 2 parallel streams adjust = delay_target + lastPacketTime.subUsec( reportstruct->packetTime ); lastPacketTime.set( reportstruct->packetTime.tv_sec, reportstruct->packetTime.tv_usec ); if ( adjust > 0 || delay > 0 ) { delay += adjust; } } // Read the next data block from // the file if it's file input if ( isFileInput( mSettings ) ) { Extractor_getNextDataBlock( readAt, mSettings ); canRead = Extractor_canRead( mSettings ) != 0; } else canRead = true; // perform write currLen = write( mSettings->mSock, mBuf, mSettings->mBufLen ); if ( currLen < 0 && errno != ENOBUFS ) { WARN_errno( currLen < 0, "write2" ); break; } // report packets reportstruct->packetLen = currLen; ReportPacket( mSettings->reporthdr, reportstruct ); if ( delay > 0 ) { delay_loop( delay ); } if ( !mMode_Time ) { mSettings->mAmount -= currLen; } } while ( ! (sInterupted || (mMode_Time && mEndTime.before( reportstruct->packetTime )) || (!mMode_Time && 0 >= mSettings->mAmount)) && canRead ); // stop timing gettimeofday( &(reportstruct->packetTime), NULL ); CloseReport( mSettings->reporthdr, reportstruct ); if ( isUDP( mSettings ) ) { // send a final terminating datagram // Don't count in the mTotalLen. The server counts this one, // but didn't count our first datagram, so we're even now. // The negative datagram ID signifies termination to the server. // store datagram ID into buffer mBuf_UDP->id = htonl( -(reportstruct->packetID) ); mBuf_UDP->tv_sec = htonl( reportstruct->packetTime.tv_sec ); mBuf_UDP->tv_usec = htonl( reportstruct->packetTime.tv_usec ); if ( isMulticast( mSettings ) ) { write( mSettings->mSock, mBuf, mSettings->mBufLen ); } else { write_UDP_FIN( ); } } DELETE_PTR( reportstruct ); EndReport( mSettings->reporthdr );} // end Runvoid Client::InitiateServer() { if ( !isCompat( mSettings ) ) { int currLen; client_hdr* temp_hdr; if ( isUDP( mSettings ) ) { UDP_datagram *UDPhdr = (UDP_datagram *)mBuf; temp_hdr = (client_hdr*)(UDPhdr + 1); } else { temp_hdr = (client_hdr*)mBuf; } Settings_GenerateClientHdr( mSettings, temp_hdr ); if ( !isUDP( mSettings ) ) { currLen = send( mSettings->mSock, mBuf, sizeof(client_hdr), 0 ); if ( currLen < 0 ) { WARN_errno( currLen < 0, "write1" ); } } }}/* ------------------------------------------------------------------- * Setup a socket connected to a server. * If inLocalhost is not null, bind to that address, specifying * which outgoing interface to use. * ------------------------------------------------------------------- */void Client::Connect( ) { int rc; SockAddr_remoteAddr( mSettings ); assert( mSettings->inHostname != NULL ); // create an internet socket int type = ( isUDP( mSettings ) ? SOCK_DGRAM : SOCK_STREAM); int domain = (SockAddr_isIPv6( &mSettings->peer ) ? #ifdef HAVE_IPV6 AF_INET6#else AF_INET#endif : AF_INET); mSettings->mSock = socket( domain, type, 0 ); WARN_errno( mSettings->mSock == INVALID_SOCKET, "socket" ); SetSocketOptions( mSettings ); SockAddr_localAddr( mSettings ); if ( mSettings->mLocalhost != NULL ) { // bind socket to local address rc = bind( mSettings->mSock, (sockaddr*) &mSettings->local, SockAddr_get_sizeof_sockaddr( &mSettings->local ) ); WARN_errno( rc == SOCKET_ERROR, "bind" ); } // connect socket rc = connect( mSettings->mSock, (sockaddr*) &mSettings->peer, SockAddr_get_sizeof_sockaddr( &mSettings->peer )); WARN_errno( rc == SOCKET_ERROR, "connect" ); getsockname( mSettings->mSock, (sockaddr*) &mSettings->local, &mSettings->size_local ); getpeername( mSettings->mSock, (sockaddr*) &mSettings->peer, &mSettings->size_peer );} // end Connect/* ------------------------------------------------------------------- * Send a datagram on the socket. The datagram's contents should signify * a FIN to the application. Keep re-transmitting until an * acknowledgement datagram is received. * ------------------------------------------------------------------- */ void Client::write_UDP_FIN( ) { int rc; fd_set readSet; struct timeval timeout; int count = 0; while ( count < 10 ) { count++; // write data write( mSettings->mSock, mBuf, mSettings->mBufLen ); // wait until the socket is readable, or our timeout expires FD_ZERO( &readSet ); FD_SET( mSettings->mSock, &readSet ); timeout.tv_sec = 0; timeout.tv_usec = 250000; // quarter second, 250 ms rc = select( mSettings->mSock+1, &readSet, NULL, NULL, &timeout ); FAIL_errno( rc == SOCKET_ERROR, "select", mSettings ); if ( rc == 0 ) { // select timed out continue; } else { // socket ready to read rc = read( mSettings->mSock, mBuf, mSettings->mBufLen ); WARN_errno( rc < 0, "read" ); if ( rc < 0 ) { break; } else if ( rc >= (int) (sizeof(UDP_datagram) + sizeof(server_hdr)) ) { ReportServerUDP( mSettings, (server_hdr*) ((UDP_datagram*)mBuf + 1) ); } return; } } fprintf( stderr, warn_no_ack, mSettings->mSock, count ); } // end write_UDP_FIN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -