UDT4協議原始碼分析之send和recv
阿新 • • 發佈:2019-02-01
int CUDT::send(UDTSOCKET u, const char* buf, int len, int) { try { CUDT* udt = s_UDTUnited.lookup(u);//這裡是通過套介面ID直接找到關聯的傳輸控制塊,而之前介紹的connect函式中,是通過套介面ID找到關聯的套介面,注意區分 return udt->send(buf, len);//可見傳進來的第三個引數沒有用 } catch (CUDTException e) { s_UDTUnited.setError(new CUDTException(e)); return ERROR; } catch (bad_alloc&) { s_UDTUnited.setError(new CUDTException(3, 2, 0)); return ERROR; } catch (...) { s_UDTUnited.setError(new CUDTException(-1, 0, 0)); return ERROR; } }
int CUDT::send(const char* data, int len) { if (UDT_DGRAM == m_iSockType)//如果是UDT_DGRAM型別,則丟擲錯誤 throw CUDTException(5, 10, 0); // throw an exception if not connected if (m_bBroken || m_bClosing) throw CUDTException(2, 1, 0); else if (!m_bConnected) throw CUDTException(2, 2, 0); if (len <= 0) return 0; CGuard sendguard(m_SendLock); if (m_pSndBuffer->getCurrBufSize() == 0)//若傳送快取中沒有資料 { // delay the EXP timer to avoid mis-fired timeout uint64_t currtime; CTimer::rdtsc(currtime); m_ullLastRspTime = currtime; } if (m_iSndBufSize <= m_pSndBuffer->getCurrBufSize())//傳送快取滿了 {//m_iSndBufSize=8192個包 if (!m_bSynSending) throw CUDTException(6, 1, 0); else { // wait here during a blocking sending #ifndef WIN32 pthread_mutex_lock(&m_SendBlockLock); if (m_iSndTimeOut < 0) //初始值為-1 { while (!m_bBroken && m_bConnected && !m_bClosing && (m_iSndBufSize <= m_pSndBuffer->getCurrBufSize()) && m_bPeerHealth) pthread_cond_wait(&m_SendBlockCond, &m_SendBlockLock); } else { uint64_t exptime = CTimer::getTime() + m_iSndTimeOut * 1000ULL; timespec locktime; locktime.tv_sec = exptime / 1000000; locktime.tv_nsec = (exptime % 1000000) * 1000; while (!m_bBroken && m_bConnected && !m_bClosing && (m_iSndBufSize <= m_pSndBuffer->getCurrBufSize()) && m_bPeerHealth && (CTimer::getTime() < exptime)) pthread_cond_timedwait(&m_SendBlockCond, &m_SendBlockLock, &locktime); } pthread_mutex_unlock(&m_SendBlockLock); ...... // check the connection status if (m_bBroken || m_bClosing) throw CUDTException(2, 1, 0); else if (!m_bConnected) throw CUDTException(2, 2, 0); else if (!m_bPeerHealth) { m_bPeerHealth = true; throw CUDTException(7); } } } if (m_iSndBufSize <= m_pSndBuffer->getCurrBufSize()) { if (m_iSndTimeOut >= 0) throw CUDTException(6, 3, 0); return 0; } int size = (m_iSndBufSize - m_pSndBuffer->getCurrBufSize()) * m_iPayloadSize;//1500-28-16=1456 if (size > len) size = len; // record total time used for sending if (0 == m_pSndBuffer->getCurrBufSize()) m_llSndDurationCounter = CTimer::getTime(); // insert the user buffer into the sening list m_pSndBuffer->addBuffer(data, size); // insert this socket to snd list if it is not on the list yet m_pSndQueue->m_pSndUList->update(this, false);//插入到m_pHeap中,signal Tick_Cond if (m_iSndBufSize <= m_pSndBuffer->getCurrBufSize()) { // write is not available any more s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, UDT_EPOLL_OUT, false); } return size; }