1. 程式人生 > >select 設置發送超時發送註意事項

select 設置發送超時發送註意事項

在那 有用 賦值 span 並發 logs 模式 ket net

//設置發送超時
你只發送, 並發送足夠多的數據以填滿發送緩沖區, 接收端一直不接收.
發送端一量滿發送緩沖區就會阻塞, 如果你設置了發送超時, 超時到了它就會返回發送超時了.

在send(),recv()過程中有時由於網絡狀況等原因,收發不能預期進行,而設置收發超時控制: 在Linux下需要註意的是時間的控制結構是struct timeval而並不是某一整型數,以下是來自於網上一篇文章中的摘錄,它是這樣寫的:
int nNetTimeout=1000;//1秒,
//設置發送超時
setsockopt(socket,SOL_SOCKET,SO_SNDTIMEO,(char *)&nNetTimeout,sizeof(int));
//設置接收超時
setsockopt(socket,SOL_SOCKET,SO_RCVTIMEO,(char *)&nNetTimeout,sizeof(int)); 這樣做在Linux環境下是不會產生效果的,須如下定義:struct timeval timeout = {3,0};
//設置發送超時
setsockopt(socket,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(struct timeval)); //設置接收超時
setsockopt(socket,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(struct timeval)); 有兩點註意就是:
1)recv ()的第四個參數需為MSG_WAITALL,在阻塞模式下不等到指定數目的數據不會返回,除非超時時間到。還要註意的是只要設置了接收超時,在沒有MSG_WAITALL時也是有效的。說到底超時就是不讓你的程序老在那兒等,到一定時間進行一次返回而已。 2)即使等待超時時間值未到,但對方已經關閉了socket, 則此時recv()會立即返回,並收到多少數據返回多少數據。

在進行程序開發時,有時候需要阻塞,但同時又需要有超時功能,這時候select()函數就能很好的滿足我們的要求:

但用這進行測試時有一個地方是需要註意的,即select()的第五個參數timeval *timeout的問題。設置好timeout的始值後,如果只對select()調用一次,是沒有任何問題的,但一旦多次調用,你就會發現怎麽好像我設置的timeout值只有第一次有用呢,以後select()總是一刻也不等就返回了呢?

通過查看man和自己測試,原來select()函數內部是會不斷更新timeout的值的,以查看超時時間還剩多少。那麽第一次調用之後,timeout的值就被更新至0了,以後不管你再調用它多少次,select()都會立即返回了,這就是為什麽會出現在多次調用時,select()只有第一次時湊效的緣由了,哈哈,以後再使用它時,要尤其註意這一點了。但它的兄弟函數pselect()沒有它的這個問題,它不會在內部在時間值進行更新的。

socket在每次執行select的時候都得要重新對time進行賦值 防止select修改了time參數 對下一次的判斷造成幹擾
for (i = 0 ; i < waittimeout ; i++)
    {
        FD_SET(fd , &fdr);
        sTime.tv_sec = 1;
        sTime.tv_usec = 0;        iRet = select(iMax , &fdr , NULL , NULL , &sTime);
        if (iRet == -1)
        {
            LOG_TRACE(&gLogger, "select -1");
            return -1;
        }
        else if (iRet > 0)
        {
            LOG_TRACE(&gLogger, "wait %ds sock readalbe, select=%d", i, iRet);
            return 0 ;
        }
    }

select 設置發送超時發送註意事項