• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            天下

            記錄修行的印記

            socket函數send和recv函數


            在發送端,一次發送4092個字節,
            在接收端,一次接收4092個字節,
            但是在接收端,偶爾會出現 socket.receive 接收不全的情況 ,

            ret 
            = sock.recv(bBuffer,iBufferLen,0); //也有可能無法收到全部數據!
            必須要考慮0 < ret < iBufferLen的情況:繼續接收iBufferLen - ret字節,然后合并
            注意第recv函數的第四個參數:
            MSG_WAITALL The receive request will complete only when one of the following events occurs:
            • The buffer supplied by the caller is completely full.
            • The connection has been closed.
            • The request has been canceled.
            Note that if the underlying transport does not support MSG_WAITALL, or if the socket is in a non-blocking mode, then this call will fail with WSAEOPNOTSUPP. Also, if MSG_WAITALL is specified along with MSG_OOB, MSG_PEEK, or MSG_PARTIAL, then this call will fail with WSAEOPNOTSUPP. This flag is not supported on datagram sockets or message-oriented CO sockets.


            Socket的Send,Recv的長度問題:

            一個包沒有固定長度,以太網限制在46-1500字節,1500就是以太網的MTU,超過這個量,TCP會為IP數據報設置偏移量進行分片傳輸,現在一般可允許應用層設置8k(NTFS系統)的緩沖區,8k的數據由底層分片,而應用層看來只是一次發送。
            windows的緩沖區經驗值是4k。
            Socket本身分為兩種,流(TCP)和數據報(UDP),你的問題針對這兩種不同使用而結論不一樣。甚至還和你是用阻塞、還是非阻塞Socket來編程有關。
            1、通信長度,這個是你自己決定的,沒有系統強迫你要發多大的包,實際應該根據需求和網絡狀況來決定。對于TCP,這個長度可以大點,但要知道,Socket內部默認的收發緩沖區大小大概是8K,你可以用SetSockOpt來改變。但對于UDP,就不要太大,一般在1024至10K。注意一點,你無論發多大的包,IP層和鏈路層都會把你的包進行分片發送,一般局域網就是1500左右,廣域網就只有幾十字節。分片后的包將經過不同的路由到達接收方,對于UDP而言,要是其中一個分片丟失,那么接收方的IP層將把整個發送包丟棄,這就形成丟包。顯然,要是一個UDP發包佷大,它被分片后,鏈路層丟失分片的幾率就佷大,你這個UDP包,就佷容易丟失,但是太小又影響效率。最好可以配置這個值,以根據不同的環境來調整到最佳狀態。
            send()函數返回了實際發送的長度,在網絡不斷的情況下,它絕不會返回(發送失敗的)錯誤,最多就是返回0。對于TCP你可以寫一個循環發送。當send函數返回SOCKET_ERROR時,才標志著有錯誤。但對于UDP,你不要寫循環發送,否則將給你的接收帶來極大的麻煩。所以UDP需要用SetSockOpt來改變Socket內部Buffer的大小,以能容納你的發包。明確一點,TCP作為流,發包是不會整包到達的,而是源源不斷的到,那接收方就必須組包。而UDP作為消息或數據報,它一定是整包到達接收方。
            2、關于接收,一般的發包都有包邊界,首要的就是你這個包的長度要讓接收方知道,于是就有個包頭信息,對于TCP,接收方先收這個包頭信息,然后再收包數據。一次收齊整個包也可以,可要對結果是否收齊進行驗證。這也就完成了組包過程。UDP,那你只能整包接收了。要是你提供的接收Buffer過小,TCP將返回實際接收的長度,余下的還可以收,而UDP不同的是,余下的數據被丟棄并返回WSAEMSGSIZE錯誤。注意TCP,要是你提供的Buffer佷大,那么可能收到的就是多個發包,你必須分離它們,還有就是當Buffer太小,而一次收不完Socket內部的數據,那么Socket接收事件(OnReceive),可能不會再觸發,使用事件方式進行接收時,密切注意這點。這些特性就是體現了流和數據包的區別。
            補充一點,接收BuffSize 
            >= 發送BuffSize >= 實際發送Size,對于內外部的Buffer都適用,上面講的主要是Socket內部的Buffer大小關系。
            3、TCP是有多少就收多少,如果沒有當然阻塞Socket的recv就會等,直到有數據,非阻塞Socket不好等,而是返回WSAEWOULDBLOCK。UDP,如果沒有數據,阻塞Socket就會等,非阻塞Socket也返回WSAEWOULDBLOCK。如果有數據,它是會等整個發包到齊,并接收到整個發包,才返回。

            send函數
            int send( SOCKET s,const char* buf,int len,int flags);

            不論是客戶還是服務器應用程序都用send函數來向TCP連接的另一端發送數據。

            客戶程序一般用send函數向服務器發送請求,而服務器則通常用send函數來向客戶程序發送應答。

            該函數的第一個參數指定發送端套接字描述符;

            第二個參數指明一個存放應用程序要發送數據的緩沖區;

            第三個參數指明實際要發送的數據的字節數;

            第四個參數一般置0。

            這里只描述同步Socket的send函數的執行流程。當調用該函數時,send先比較待發送數據的長度len和套接字s的發送緩沖的 長度,如果len大于s的發送緩沖區的長度,該函數返回SOCKET_ERROR;如果len小于或者等于s的發送緩沖區的長度,那么send先檢查協議 是否正在發送s的發送緩沖中的數據,如果是就等待協議把數據發送完,如果協議還沒有開始發送s的發送緩沖中的數據或者s的發送緩沖中沒有數據,那么 send就比較s的發送緩沖區的剩余空間和len,如果len大于剩余空間大小send就一直等待協議把s的發送緩沖中的數據發送完,如果len小于剩余 空間大小send就僅僅把buf中的數據copy到剩余空間里(注意并不是send把s的發送緩沖中的數據傳到連接的另一端的,而是協議傳的,send僅僅是把buf中的數據copy到s的發送緩沖區的剩余空間里)。如果send函數copy數據成功,就返回實際copy的字節數,如果send在copy數據時出現錯誤,那么send就返回SOCKET_ERROR;如果send在等待協議傳送數據時網絡斷開的話,那么send函數也返回SOCKET_ERROR。

            要注意send函數把buf中的數據成功copy到s的發送緩沖的剩余空間里后它就返回了,但是此時這些數據并不一定馬上被傳到連接的另一端。如 果協議在后續的傳送過程中出現網絡錯誤的話,那么下一個Socket函數就會返回SOCKET_ERROR。(每一個除send外的Socket函數在執 行的最開始總要先等待套接字的發送緩沖中的數據被協議傳送完畢才能繼續,如果在等待時出現網絡錯誤,那么該Socket函數就返回 SOCKET_ERROR)

            注意:在Unix系統下,如果send在等待協議傳送數據時網絡斷開的話,調用send的進程會接收到一個SIGPIPE信號,進程對該信號的默認處理是進程終止。

            recv函數

            int recv( SOCKET s,char* buf,int len,int flags);   

            不論是客戶還是服務器應用程序都用recv函數從TCP連接的另一端接收數據。

            該函數的第一個參數指定接收端套接字描述符;

            第二個參數指明一個緩沖區,該緩沖區用來存放recv函數接收到的數據;

            第三個參數指明buf的長度;

            第四個參數一般置0。

            這里只描述同步Socket的recv函數的執行流程。當應用程序調用recv函數時,recv先等待s的發送緩沖 中的數據被協議傳送完畢,如果協議在傳送s的發送緩沖中的數據時出現網絡錯誤,那么recv函數返回SOCKET_ERROR,如果s的發送緩沖中沒有數 據或者數據被協議成功發送完畢后,recv先檢查套接字s的接收緩沖區,如果s接收緩沖區中沒有數據或者協議正在接收數據,那么recv就一直等待,只到 協議把數據接收完畢。當協議把數據接收完畢,recv函數就把s的接收緩沖中的數據copy到buf中(注意協議接收到的數據可能大于buf的長度,所以 在這種情況下要調用幾次recv函數才能把s的接收緩沖中的數據copy完。recv函數僅僅是copy數據,真正的接收數據是協議來完成的),recv函數返回其實際copy的字節數。如果recv在copy時出錯,那么它返回SOCKET_ERROR;如果recv函數在等待協議接收數據時網絡中斷了,那么它返回0。

            注意:在Unix系統下,如果recv函數在等待協議接收數據時網絡斷開了,那么調用recv的進程會接收到一個SIGPIPE信號,進程對該信號的默認處理是進程終止。


            #include 
            "socketclient.h"
            int main()
            {
                SocketClient cli;
                
            char* szIp    = "127.0.0.1";
                WORD  wPort 
            = 5082;
                
            int nRet = cli.Open(szIp,wPort);
                
            if (nRet!=0)
                {
                    printf(
            "Open %s:%d error:%d \r\n",szIp,wPort,nRet);
                    
            return -1;
                }
                
            char buf[1600];
                
            int i=1;
                DWORD dwTickCount0 
            = 0;
                DWORD dwTickCount1 
            = 0;
                
            int nSended = 0;
                
            while (1)
                {
                    dwTickCount0 
            = cli.GetTickCount();
                    
            //printf("%d,TickCount(0):%u \r\n",i,dwTickCount0);

                    nSended 
            = cli.Send(buf,1500); //超時2秒發送

                    dwTickCount1 
            = cli.GetTickCount();
                    
            //printf("%d,TickCount(1):%u \r\n",i,dwTickCount1);
                    
            //usleep(20*100);
                    printf("%d,time:%u,sended:%d,err:%d \r\n",i,dwTickCount1 - dwTickCount0,nSended,errno);
                    
            if (nSended<1)
                    {
                        
            break;
                    }
                    i
            ++;
                }
            }

            1,time:0,sended:1500,err:0 
            2,time:0,sended:1500,err:0 
            3,time:0,sended:1500,err:0 
            4,time:0,sended:1500,err:0 
            5,time:0,sended:1500,err:0 
            6,time:0,sended:1500,err:0 
            7,time:0,sended:1500,err:0 
            8,time:1,sended:1500,err:0 
            9,time:0,sended:1500,err:0 
            10,time:0,sended:1500,err:0 
            11,time:0,sended:1500,err:0 
            12,time:0,sended:1500,err:0 
            13,time:0,sended:1500,err:0 
            14,time:0,sended:1500,err:0 
            15,time:0,sended:1500,err:0 
            16,time:0,sended:1500,err:0 
            17,time:0,sended:1500,err:0 
            18,time:0,sended:1500,err:0 
            19,time:0,sended:1500,err:0 
            20,time:0,sended:1500,err:0 
            21,time:0,sended:1500,err:0 
            22,time:0,sended:1500,err:0 
            23,time:0,sended:1500,err:0 
            24,time:0,sended:1500,err:0 
            25,time:0,sended:1500,err:0 
            26,time:0,sended:1500,err:0 
            27,time:0,sended:1500,err:0 
            28,time:0,sended:1500,err:0 
            29,time:0,sended:1500,err:0 
            30,time:0,sended:1500,err:0 
            31,time:0,sended:1500,err:0 
            32,time:0,sended:1500,err:0 
            33,time:0,sended:1500,err:0 
            34,time:0,sended:1500,err:0 
            35,time:0,sended:1500,err:0 
            36,time:0,sended:1500,err:0 
            37,time:0,sended:1500,err:0 
            38,time:0,sended:1500,err:0 
            39,time:0,sended:1500,err:0 
            40,time:0,sended:1500,err:0 
            41,time:0,sended:1500,err:0 
            42,time:0,sended:1500,err:0 
            43,time:0,sended:1500,err:0 
            44,time:0,sended:1500,err:0 
            45,time:0,sended:1500,err:0 
            46,time:0,sended:1500,err:0 
            47,time:0,sended:1500,err:0 
            48,time:39,sended:1500,err:0 
            49,time:0,sended:1500,err:0 
            50,time:0,sended:1500,err:0 
            51,time:0,sended:1500,err:0 
            52,time:0,sended:1500,err:0 
            53,time:0,sended:1500,err:0 
            54,time:0,sended:1500,err:0 
            55,time:0,sended:1500,err:0 
            56,time:0,sended:1500,err:0 
            57,time:0,sended:1500,err:0 
            58,time:0,sended:1500,err:0 
            59,time:0,sended:1500,err:0 
            60,time:0,sended:1500,err:0 
            61,time:0,sended:1500,err:0 
            62,time:0,sended:1500,err:0 
            63,time:0,sended:1500,err:0 
            64,time:0,sended:1500,err:0 
            65,time:0,sended:1500,err:0 
            66,time:0,sended:1500,err:0 
            67,time:0,sended:1500,err:0 
            68,time:0,sended:1500,err:0 
            69,time:0,sended:1500,err:0 
            70,time:0,sended:1500,err:0 
            71,time:0,sended:1500,err:0 
            72,time:0,sended:1500,err:0 
            73,time:0,sended:1500,err:0 
            74,time:0,sended:1500,err:0 
            75,time:0,sended:1500,err:0 
            76,time:0,sended:1500,err:0 
            77,time:0,sended:1500,err:0 
            78,time:0,sended:1500,err:0 
            79,time:0,sended:1500,err:0 
            80,time:0,sended:1500,err:0 
            81,time:0,sended:1500,err:0 
            82,time:0,sended:1500,err:0 
            83,time:0,sended:1500,err:0 
            84,time:0,sended:1500,err:0 
            85,time:0,sended:1500,err:0 
            86,time:0,sended:1500,err:0 
            87,time:0,sended:1500,err:0 
            88,time:0,sended:1500,err:0 
            89,time:0,sended:1500,err:0 
            90,time:0,sended:1500,err:0 
            91,time:0,sended:1500,err:0 
            92,time:0,sended:1500,err:0 
            93,time:0,sended:1500,err:0 
            94,time:0,sended:1500,err:0 
            95,time:0,sended:1500,err:0 
            96,time:0,sended:1500,err:0 
            97,time:0,sended:1500,err:0 
            98,time:0,sended:1500,err:0 
            99,time:0,sended:1500,err:0 
            100,time:0,sended:1500,err:0 
            101,time:0,sended:1500,err:0 
            102,time:0,sended:1500,err:0 
            103,time:0,sended:1500,err:0 
            104,time:0,sended:1500,err:0 
            105,time:0,sended:1500,err:0 
            106,time:0,sended:1500,err:0 
            107,time:0,sended:1500,err:0 
            108,time:0,sended:1500,err:0 
            109,time:0,sended:1500,err:0 
            110,time:0,sended:1500,err:0 
            111,time:0,sended:1500,err:0 
            112,time:0,sended:1500,err:0 
            113,time:0,sended:1500,err:0 
            114,time:0,sended:1500,err:0 
            115,time:0,sended:1500,err:0 
            116,time:0,sended:1500,err:0 
            117,time:0,sended:1500,err:0 
            118,time:0,sended:1500,err:0 
            119,time:0,sended:1500,err:0 
            120,time:0,sended:1500,err:0 
            121,time:0,sended:1500,err:0 
            122,time:0,sended:1500,err:0 
            123,time:0,sended:1500,err:0 
            124,time:0,sended:1500,err:0 
            125,time:1999,sended:340,err:0 //這里出現了發送不全
            126,time:0,sended:1500,err:0 
            127,time:0,sended:1500,err:0 
            128,time:0,sended:1500,err:0 
            129,time:0,sended:1500,err:0 
            130,time:0,sended:1500,err:0 
            131,time:0,sended:1500,err:0 
            132,time:0,sended:1500,err:0 
            133,time:0,sended:1500,err:0 
            134,time:0,sended:1500,err:0 
            135,time:0,sended:1500,err:0 
            136,time:0,sended:1500,err:0 
            137,time:0,sended:1500,err:0 
            138,time:0,sended:1500,err:0 
            139,time:0,sended:1500,err:0 
            140,time:0,sended:1500,err:0 
            141,time:0,sended:1500,err:0 
            142,time:0,sended:1500,err:0 
            143,time:0,sended:1500,err:0 
            144,time:0,sended:1500,err:0 
            145,time:0,sended:1500,err:0 
            146,time:0,sended:1500,err:0 
            147,time:2000,sended:1268,err:0 
            148,time:2000,sended:-1,err:11

            同樣send也會出現和recv一樣,會有發送不全的現象.

            posted on 2012-04-27 09:14 天下 閱讀(41086) 評論(0)  編輯 收藏 引用 所屬分類: Socket

            <2011年11月>
            303112345
            6789101112
            13141516171819
            20212223242526
            27282930123
            45678910

            導航

            統計

            常用鏈接

            留言簿(4)

            隨筆分類(378)

            隨筆檔案(329)

            鏈接

            最新隨筆

            搜索

            最新評論

            亚洲一本综合久久| 久久婷婷五月综合国产尤物app| 国产成人久久激情91| 国产精品99久久久久久董美香| 久久午夜电影网| 亚洲一区精品伊人久久伊人| 欧美熟妇另类久久久久久不卡 | 亚洲午夜久久影院| 亚洲国产天堂久久综合| 久久久av波多野一区二区| 国产精品美女久久久久av爽 | 久久亚洲AV成人无码国产| 色偷偷888欧美精品久久久| 日本WV一本一道久久香蕉| 久久亚洲欧美日本精品| 亚洲国产精品无码久久久不卡| 久久成人永久免费播放| 久久精品夜夜夜夜夜久久| 久久经典免费视频| Xx性欧美肥妇精品久久久久久| 亚洲av日韩精品久久久久久a | 人妻精品久久久久中文字幕| 嫩草伊人久久精品少妇AV| 久久无码国产| 久久久WWW成人| 国产99久久久久久免费看| 性色欲网站人妻丰满中文久久不卡| 久久午夜无码鲁丝片午夜精品| 婷婷综合久久狠狠色99h| 人妻无码久久一区二区三区免费 | 久久久久噜噜噜亚洲熟女综合| 国产精品对白刺激久久久| 久久中文字幕精品| 久久人妻无码中文字幕| 偷偷做久久久久网站| 亚洲成av人片不卡无码久久| 丁香五月综合久久激情| 日韩精品国产自在久久现线拍| 伊人色综合久久天天| 精品国产青草久久久久福利| 精品99久久aaa一级毛片|