• <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函數(shù)send和recv函數(shù)


            在發(fā)送端,一次發(fā)送4092個(gè)字節(jié),
            在接收端,一次接收4092個(gè)字節(jié),
            但是在接收端,偶爾會(huì)出現(xiàn) socket.receive 接收不全的情況 ,

            ret 
            = sock.recv(bBuffer,iBufferLen,0); //也有可能無法收到全部數(shù)據(jù)!
            必須要考慮0 < ret < iBufferLen的情況:繼續(xù)接收iBufferLen - ret字節(jié),然后合并
            注意第recv函數(shù)的第四個(gè)參數(shù):
            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的長度問題:

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

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

            不論是客戶還是服務(wù)器應(yīng)用程序都用send函數(shù)來向TCP連接的另一端發(fā)送數(shù)據(jù)。

            客戶程序一般用send函數(shù)向服務(wù)器發(fā)送請(qǐng)求,而服務(wù)器則通常用send函數(shù)來向客戶程序發(fā)送應(yīng)答。

            該函數(shù)的第一個(gè)參數(shù)指定發(fā)送端套接字描述符;

            第二個(gè)參數(shù)指明一個(gè)存放應(yīng)用程序要發(fā)送數(shù)據(jù)的緩沖區(qū);

            第三個(gè)參數(shù)指明實(shí)際要發(fā)送的數(shù)據(jù)的字節(jié)數(shù);

            第四個(gè)參數(shù)一般置0。

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

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

            注意:在Unix系統(tǒng)下,如果send在等待協(xié)議傳送數(shù)據(jù)時(shí)網(wǎng)絡(luò)斷開的話,調(diào)用send的進(jìn)程會(huì)接收到一個(gè)SIGPIPE信號(hào),進(jìn)程對(duì)該信號(hào)的默認(rèn)處理是進(jìn)程終止。

            recv函數(shù)

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

            不論是客戶還是服務(wù)器應(yīng)用程序都用recv函數(shù)從TCP連接的另一端接收數(shù)據(jù)。

            該函數(shù)的第一個(gè)參數(shù)指定接收端套接字描述符;

            第二個(gè)參數(shù)指明一個(gè)緩沖區(qū),該緩沖區(qū)用來存放recv函數(shù)接收到的數(shù)據(jù);

            第三個(gè)參數(shù)指明buf的長度;

            第四個(gè)參數(shù)一般置0。

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

            注意:在Unix系統(tǒng)下,如果recv函數(shù)在等待協(xié)議接收數(shù)據(jù)時(shí)網(wǎng)絡(luò)斷開了,那么調(diào)用recv的進(jìn)程會(huì)接收到一個(gè)SIGPIPE信號(hào),進(jìn)程對(duì)該信號(hào)的默認(rèn)處理是進(jìn)程終止。


            #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); //超時(shí)2秒發(fā)送

                    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 //這里出現(xiàn)了發(fā)送不全
            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也會(huì)出現(xiàn)和recv一樣,會(huì)有發(fā)送不全的現(xiàn)象.

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

            <2012年4月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            293012345

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            留言簿(4)

            隨筆分類(378)

            隨筆檔案(329)

            鏈接

            最新隨筆

            搜索

            最新評(píng)論

            免费一级欧美大片久久网| 国产精品久久久久久久app| 亚洲人成网亚洲欧洲无码久久| 国产精品99久久久久久www| 久久国产精品成人免费| 99久久久精品免费观看国产| 人妻精品久久久久中文字幕69| 久久国产精品无| 久久久久国产精品人妻| 久久久噜噜噜久久中文字幕色伊伊 | 日本强好片久久久久久AAA| 久久久久久综合网天天| 久久99九九国产免费看小说| 亚洲国产精品一区二区三区久久 | 久久久久久亚洲精品无码| Xx性欧美肥妇精品久久久久久| 久久天堂电影网| 国产99久久久国产精免费| 91久久成人免费| 欧美国产精品久久高清| 精品久久久久久久久免费影院| 久久久SS麻豆欧美国产日韩| 久久精品国产乱子伦| 人妻无码中文久久久久专区| 国产99久久精品一区二区| 91精品国产91热久久久久福利| 66精品综合久久久久久久| 日韩电影久久久被窝网| 日本五月天婷久久网站| 97久久综合精品久久久综合| 国产女人aaa级久久久级| 久久人人爽人人人人爽AV| 久久国产精品无码HDAV| 国产精品久久久久一区二区三区| 亚洲日本va午夜中文字幕久久| 日韩精品久久久肉伦网站 | 国产午夜精品理论片久久| 精品国产日韩久久亚洲| 国产成人精品久久一区二区三区| 久久996热精品xxxx| 无码AV波多野结衣久久|