• <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>

            Benjamin

            靜以修身,儉以養(yǎng)德,非澹薄無以明志,非寧靜無以致遠。
            隨筆 - 398, 文章 - 0, 評論 - 196, 引用 - 0
            數(shù)據(jù)加載中……

            tcp中的粘包、半包的處理方法

                  TCP粘包是指發(fā)送方發(fā)送的若干包數(shù)據(jù)到接收方接收時粘成一包,從接收緩沖區(qū)看,后一包數(shù)據(jù)的頭緊接著前一包數(shù)據(jù)的尾。

              出現(xiàn)粘包現(xiàn)象的原因既可能由發(fā)送方造成,也可能由接收方造成。
            發(fā)送方引起的粘包是由TCP協(xié)議本身造成的,TCP為提高傳輸效率,發(fā)送方往往要收集到足夠多的數(shù)據(jù)后才發(fā)送一包數(shù)據(jù)。若連續(xù)幾次發(fā)送的數(shù)據(jù)都很少,通常TCP會根據(jù)優(yōu)化算法把這些數(shù)據(jù)合成一包后一次發(fā)送出去,這樣接收方就收到了粘包數(shù)據(jù)。
                  接收方引起的粘包是由于接收方用戶進程不及時接收數(shù)據(jù),從而導致粘包現(xiàn)象。這是因為接收方先把收到的數(shù)據(jù)放在系統(tǒng)接收緩沖區(qū),用戶進程從該緩沖區(qū)取數(shù)據(jù),若下一包數(shù)據(jù)到達時前一包數(shù)據(jù)尚未被用戶進程取走,則下一包數(shù)據(jù)放到系統(tǒng)接收緩沖區(qū)時就接到前一包數(shù)據(jù)之后,而用戶進程根據(jù)預先設定的緩沖區(qū)大小從系統(tǒng)接收緩沖區(qū)取數(shù)據(jù),這樣就一次取到了多包數(shù)據(jù)。
            c++的解決方法如下:接收端
                int iRecvSize = PackteSize + 10;
                int iRet;
               int idx = 0;
               while (iRecvSize > 0)
               {
                iRet = recv(AcceptSocket, recvbuf+idx, iRecvSize, 0);
                if (iRet > 0)
                {
                 idx += iRet;
                 iRecvSize -= iRet;
                }
                else if (iRet == 0)
                {
                 break;
                }
                else if ( iRet == SOCKET_ERROR)
                {
                 break;
                }
               }
            發(fā)送端:
               int iSendSize = PacketSize + 10;
               int iSent;
               int idx = 0;
               while (iSendSize > 0)
               {
                iSent = send(m_socket,sendbuffer+idx,iSendSize,0);
                if (iSent > 0)
                {
                 idx += iSent;
                 iSendSize -= iSent;
                }
                else if (iSent == 0)
                {
                 break;
                }
                else if (iSent == SOCKET_ERROR)
                {
                 wprintf(L"send failed with error: %d\n", WSAGetLastError());
                 //closesocket(m_socket);
                 //WSACleanup();
                 break;
                }
               }
            若傳輸?shù)臄?shù)據(jù)為不帶結(jié)構(gòu)的連續(xù)流數(shù)據(jù)(如文件傳輸),則不必把粘連的包分開(簡稱分包),反之則必須分包。
            c#中用socket的Available成員來表示是否還有數(shù)據(jù)需要讀取,如果Available>0,表示還有數(shù)據(jù)需有讀取,反之讀取完成。

              public class ConnectInfo
                {
                    public ArrayList tmpList { get; set; }
                    public SocketAsyncEventArgs SendArg { get; set; }
                    public SocketAsyncEventArgs ReceiveArg { get; set; }
                    public Socket ServerSocket { get; set; }
                    public User user = new User();

                }


                 if (client.Available > 0)
                  {
                                Console.WriteLine("粘包處理");
                                for (int i = 0; i < rec; i++)
                                    info.tmpList.Add(datas[i]);
                                Array.Clear(datas, 0, datas.Length);

                                datas = new byte[client.Available];
                                e.SetBuffer(datas, 0, datas.Length);
                                client.ReceiveAsync(e);
                               
                   }
                   else
                   {
                                //檢查暫存數(shù)據(jù)的ArrayList中有沒有數(shù)據(jù),有就和本次的數(shù)據(jù)合并
                                if (info.tmpList.Count > 0)
                                {
                                    for (int i = 0; i < rec; i++)
                                        info.tmpList.Add(datas[i]);
                                    datas = info.tmpList.ToArray(typeof(byte)) as byte[];
                                    rec = datas.Length;
                                }

                                //對接收的完整數(shù)據(jù)進行處理
                   }

            半包顧名思義,就不是一個完整的包,tcp發(fā)出一個段后,它啟動一個定時器,等待目的端確認收到這個報文段。如果不能及時收到一個確認,將重發(fā)這個報文段。
            常見的解決方法就是制定規(guī)范的數(shù)據(jù)傳輸格式。

            posted on 2013-09-22 21:22 Benjamin 閱讀(4994) 評論(0)  編輯 收藏 引用 所屬分類: C/C++

            9191精品国产免费久久| 久久久久久综合一区中文字幕| 久久国产成人午夜AV影院| 久久久久久噜噜精品免费直播 | 香蕉久久夜色精品国产尤物| 久久久这里有精品| 2021精品国产综合久久| 久久久久亚洲AV无码专区桃色| 久久天天躁夜夜躁狠狠| 91久久精品国产成人久久| 伊人久久大香线蕉综合影院首页 | 热re99久久精品国产99热| 久久亚洲精品国产精品婷婷 | 欧美无乱码久久久免费午夜一区二区三区中文字幕 | 狠狠久久亚洲欧美专区| 一本久道久久综合狠狠躁AV| 久久狠狠高潮亚洲精品| 亚洲人AV永久一区二区三区久久| 久久久久人妻一区精品色| 久久人人爽人人人人片av| 国内精品免费久久影院| 久久国产精品一国产精品金尊| 亚洲伊人久久综合中文成人网| 久久99精品国产麻豆婷婷| 久久国产精品成人免费| 久久婷婷国产麻豆91天堂| 久久久久久久久久久久中文字幕 | 久久国产精品视频| 91精品国产高清久久久久久91| 亚洲精品无码久久久影院相关影片 | 午夜精品久久久久久久无码| 国产AV影片久久久久久| 国产L精品国产亚洲区久久| 国产精品福利一区二区久久| 精品少妇人妻av无码久久| 久久精品国产亚洲AV无码娇色| 蜜臀av性久久久久蜜臀aⅴ| 无码精品久久久久久人妻中字| 性做久久久久久久| 99久久99久久久精品齐齐| 麻豆精品久久精品色综合|