日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
C#Socket通信三大問(wèn)題詳解

C# Socket通信三大問(wèn)題是什么呢?讓我們開始講述:

利辛網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)公司!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、響應(yīng)式網(wǎng)站建設(shè)等網(wǎng)站項(xiàng)目制作,到程序開發(fā),運(yùn)營(yíng)維護(hù)。成都創(chuàng)新互聯(lián)公司從2013年創(chuàng)立到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選成都創(chuàng)新互聯(lián)公司。

C# Socket通信三大問(wèn)題之?dāng)?shù)據(jù)包界限符問(wèn)題。

根據(jù)原項(xiàng)目中交通部標(biāo)準(zhǔn),在連續(xù)觀測(cè)站中數(shù)據(jù)包中,使用﹤﹥兩個(gè)字符表示有效數(shù)據(jù)包開始和結(jié)束。實(shí)際項(xiàng)目有各自的具體技術(shù)規(guī)范

C# Socket通信三大問(wèn)題之?dāng)?shù)據(jù)包不連續(xù)問(wèn)題。

在TCP/IP等通信中,由于時(shí)延等原因,一個(gè)數(shù)據(jù)包被Socket做兩次或多次接收,此時(shí)在接收第一個(gè)包后,必須保存到TSession的DatagramBuffer中,在以后一并處理

C# Socket通信三大問(wèn)題包并發(fā)與重疊問(wèn)題。

由于客戶端發(fā)送過(guò)快或設(shè)備故障等原因,一次接收到一個(gè)半、兩個(gè)或多個(gè)包文。此時(shí),也需要處理、一個(gè)半、兩個(gè)或多個(gè)包

先補(bǔ)充異步BeginReceive()回調(diào)函數(shù)EndReceiveData()中的數(shù)據(jù)包分合函數(shù)ResolveBuffer()。

下面是C# Socket通信三大問(wèn)題的實(shí)例演示:

 
 
 
  1. /// ﹤summary﹥  
  2. /// 1) 報(bào)文界限字符為﹤﹥,其它為合法字符,   
  3. /// 2) 按報(bào)文頭、界限標(biāo)志抽取報(bào)文,可能合并包文  
  4. /// 3) 如果一次收完數(shù)據(jù),此時(shí) DatagramBuffer 為空  
  5. /// 4) 否則轉(zhuǎn)存到包文緩沖區(qū) session.DatagramBuffer  
  6. /// ﹤/summary﹥  
  7. private void ResolveBuffer(TSession session, int receivedSize)  
  8. {  
  9. // 上次留下的報(bào)文緩沖區(qū)非空(注意:必然含有開始字符 ﹤,空時(shí)不含 ﹤)  
  10. bool hasBeginChar = (session.DatagramBufferLength ﹥ 0);   
  11.  
  12. int packPos = 0;  // ReceiveBuffer 緩沖區(qū)中包的開始位置  
  13. int packLen = 0;  // 已經(jīng)解析的接收緩沖區(qū)大小  
  14.  
  15. byte dataByte = 0;  // 緩沖區(qū)字節(jié)  
  16. int subIndex = 0;   // 緩沖區(qū)下標(biāo)  
  17.  
  18. while (subIndex ﹤ receivedSize)  
  19. {  
  20.    // 接收緩沖區(qū)數(shù)據(jù),要與報(bào)文緩沖區(qū) session.DatagramBuffer 同時(shí)考慮  
  21.    dataByte = session.ReceiveBuffer[subIndex];  
  22.      
  23.    if (dataByte == TDatagram.BeginChar) // 是數(shù)據(jù)包的開始字符﹤,則前面的包文均要放棄  
  24.    {  
  25.   // ﹤前面有非空串(包括報(bào)文緩沖區(qū)),則前面是錯(cuò)包文,防止 AAA﹤A,1,A﹥ 兩個(gè)報(bào)文一次讀現(xiàn)象  
  26.   if (packLen ﹥ 0)    
  27.   {  
  28.  Interlocked.Increment(ref _datagramCount);  // 前面有非空字符  
  29.  Interlocked.Increment(ref _errorDatagramCount);  // 一個(gè)錯(cuò)誤包  
  30.  this.OnDatagramError();  
  31.   }  
  32.   session.ClearDatagramBuffer();  // 清空會(huì)話緩沖區(qū),開始一個(gè)新包  
  33.  
  34.   packPos = subIndex;   // 新包起點(diǎn),即﹤所在位置  
  35.   packLen = 1;// 新包的長(zhǎng)度(即﹤)  
  36.   hasBeginChar = true;  // 新包有開始字符  
  37.    }     
  38.    else if (dataByte == TDatagram.EndChar)  // 數(shù)據(jù)包的結(jié)束字符 ﹥  
  39.    {  
  40.   if (hasBeginChar)  // 兩個(gè)緩沖區(qū)中有開始字符﹤  
  41.   {  
  42.  ++packLen;  // 長(zhǎng)度包括結(jié)束字符﹥  
  43.  
  44.  // ﹥前面的為正確格式的包,則分析該包,并準(zhǔn)備加入包隊(duì)列  
  45.  AnalyzeOneDatagram(session, packPos, packLen);  
  46.  
  47.  packPos = subIndex + 1;  // 新包起點(diǎn)。注意:subIndex 在循環(huán)最后處 + 1  
  48.  packLen = 0;   // 新包長(zhǎng)度  
  49.   }  
  50.   else  // ﹥前面沒(méi)有開始字符,則認(rèn)為結(jié)束字符﹥?yōu)橐话阕址?,待后續(xù)的錯(cuò)誤包處理  
  51.   {  
  52.  ++packLen;  //  hasBeginChar = false;  
  53.   }  
  54.    }  
  55.    else  // 非界限字符﹤﹥,就是是一般字符,長(zhǎng)度 + 1,待解析包處理  
  56.    {  
  57.   ++packLen;  
  58.    }  
  59.    ++subIndex;  // 增加下標(biāo)號(hào)  
  60. }  // end while  
  61.  
  62. if (packLen ﹥ 0)  // 剩下的待處理串,分兩種情況  
  63. {  
  64.    // 剩下包文,已經(jīng)包含首字符且不超長(zhǎng),轉(zhuǎn)存到包文緩沖區(qū)中,待下次處理  
  65.    if (hasBeginChar && packLen + 
  66. session.DatagramBufferLength ﹤= _maxDatagramSize)  
  67.    {  
  68.   session.CopyToDatagramBuffer(packPos, packLen);  
  69.    }  
  70.    else  // 不含首字符,或超長(zhǎng)  
  71.    {  
  72.   Interlocked.Increment(ref _datagramCount);  
  73.   Interlocked.Increment(ref _errorDatagramCount);  
  74.  
  75.   this.OnDatagramError();  
  76.   session.ClearDatagramBuffer();  // 丟棄全部數(shù)據(jù)  
  77.    }  
  78. }  
  79. }  

C# Socket通信三大問(wèn)題之分析包文AnalyzeOneDatagram()函數(shù)代碼補(bǔ)充如下:

 
 
 
  1. /// ﹤summary﹥  
  2. /// 具有﹤﹥格式的數(shù)據(jù)包加入到隊(duì)列中  
  3. /// ﹤/summary﹥  
  4. private void AnalyzeOneDatagram(  
  5. TSession session, int packPos, int packLen)  
  6. {  
  7. if (packLen + session.DatagramBufferLength ﹥ _maxDatagramSize)    
  8. // 超過(guò)長(zhǎng)度限制  
  9. {  
  10.    Interlocked.Increment(ref _datagramCount);  
  11.    Interlocked.Increment(ref _errorDatagramCount);  
  12.    this.OnDatagramError();  
  13. }  
  14. else // 一個(gè)首尾字符相符的包,此時(shí)需要判斷其類型  
  15. {  
  16.    Interlocked.Increment(ref _datagramCount);  
  17.    TDatagram datagram = new TDatagram();  
  18.  
  19.    if (!datagram.CheckDatagramKind())    
  20. // 包格式錯(cuò)誤(只能是短期BG、或長(zhǎng)期SG包)  
  21.    {  
  22.   Interlocked.Increment(ref _datagramCount);  
  23.   Interlocked.Increment(ref _errorDatagramCount);  
  24.   this.OnDatagramError();  
  25.   datagram = null;  // 丟棄當(dāng)前包  
  26.    }  
  27.    else  // 實(shí)時(shí)包、定期包,先解析數(shù)據(jù),判斷正誤,并發(fā)回確認(rèn)包  
  28.    {  
  29.   datagram.ResolveDatagram();  
  30.   if (true)  // 正確的包才入包隊(duì)列  
  31.   {  
  32.  Interlocked.Increment(ref _datagramQueueCount);  
  33.  lock (_datagramQueue)  
  34.  {  
  35. _datagramQueue.Enqueue(datagram);  // 數(shù)據(jù)包入隊(duì)列  
  36.  }  
  37.   }  
  38.   else 
  39.   {  
  40.  Interlocked.Increment(ref _errorDatagramCount);  
  41.  this.OnDatagramError();  
  42.   }  
  43.    }  
  44. }  
  45. session.ClearDatagramBuffer();  // 清包文緩沖區(qū)  

C# Socket通信三大問(wèn)題之TSession的拷貝轉(zhuǎn)存數(shù)據(jù)包文的方法CopyToDatagramBuffer()代碼如下:

 
 
 
  1. /// ﹤summary﹥  
  2. /// 拷貝接收緩沖區(qū)的數(shù)據(jù)到數(shù)據(jù)緩沖區(qū)(即多次讀一個(gè)包文)  
  3. /// ﹤/summary﹥  
  4. public void CopyToDatagramBuffer(int startPos, int packLen)    
  5. {  
  6. int datagramLen = 0;  
  7. if (DatagramBuffer != null) datagramLen =   
  8. DatagramBuffer.Length;  
  9.  
  10. // 調(diào)整長(zhǎng)度(DataBuffer 為 null 不會(huì)出錯(cuò))  
  11. Array.Resize(ref DatagramBuffer,   
  12. datagramLen + packLen);  
  13.  
  14. // 拷貝到數(shù)據(jù)就緩沖區(qū)  
  15. Array.Copy(ReceiveBuffer, startPos,   
  16. DatagramBuffer, datagramLen, packLen);  
  17. }  

代碼中注釋比較詳細(xì)了,下面指出C# Socket通信三大問(wèn)題實(shí)例開發(fā)思路:

使用TSession會(huì)話對(duì)象的字節(jié)數(shù)組ReceiveBuffer保存BeginReceiver()接收到的數(shù)據(jù),使用字節(jié)數(shù)組DatagramBuffer保存一次接收后分解或合并的剩下的包文。本項(xiàng)目中,由于是5分鐘一個(gè)包,正常情況下不需要用到DatagramBuffer數(shù)組

處理ReceiveBuffer中的字節(jié)數(shù)據(jù)包時(shí),先考慮DatagramBuffer是否有開始字符﹤。如果有,則當(dāng)前包文是前個(gè)包文的補(bǔ)充,否則前個(gè)包文是錯(cuò)誤的。正確的包文可能存在于兩個(gè)緩沖區(qū)中,見分析函數(shù)AnalyzeOneDatagram()

分析完接收數(shù)據(jù)包后,剩下的轉(zhuǎn)存到DatagramBuffer中,見函數(shù)CopyToDatagramBuffer()

設(shè)計(jì)時(shí)考慮的另一個(gè)重要問(wèn)題就是處理速度。如果自動(dòng)觀測(cè)站達(dá)到100個(gè),此時(shí)5*60=300秒鐘就有100個(gè)包,即每3秒種一個(gè)包,不存在處理速度慢問(wèn)題。但是,真正耗時(shí)的是判斷包是否重復(fù)!特別地,當(dāng)設(shè)備故障時(shí)存在混亂上傳數(shù)據(jù)包現(xiàn)象,此時(shí)將存在大量的重復(fù)包。筆者采用了所謂的區(qū)間判重算法,較好地解決了判重速度問(wèn)題,使得系統(tǒng)具有很好的可伸縮性(分析算法的論文被EI核心版收錄,呵呵,意外收獲)。事實(shí)上,前年的交通部接收服務(wù)器還不具備該項(xiàng)功能,可能是太費(fèi)時(shí)間了。

還有,就是在.NET Framework的托管CLR下,系統(tǒng)本身的響應(yīng)速度如何?當(dāng)時(shí)的確沒(méi)有把握,認(rèn)為只要穩(wěn)定性和速度滿足要求就行了。三年半運(yùn)行情況表明,系統(tǒng)有良好的處理速度、很好的穩(wěn)定性、滿足了部省要求。

C# Socket通信三大問(wèn)題的基本內(nèi)容就向你介紹到這里了,希望對(duì)你了解和學(xué)習(xí)C# Socket通信三大問(wèn)題有所幫助。


當(dāng)前標(biāo)題:C#Socket通信三大問(wèn)題詳解
本文路徑:http://www.5511xx.com/article/ccdoeip.html