自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

詳解通過.NET緩存提高TCP傳輸速度

開發(fā) 后端
在這里我們將討論的是通過.NET緩存提高TCP傳輸速度,希望對(duì)大家了解.NET機(jī)制有所幫助。

在這里我們將介紹的是通過.NET緩存提高TCP傳輸速度,這也是提高網(wǎng)絡(luò)性能的方法,希望對(duì)大家有所幫助。

.NET提供了一個(gè)NetworkStream 用于TCP 的讀寫,實(shí)際使用時(shí)發(fā)現(xiàn)直接操作效率很低,哪怕把TCP 的發(fā)送緩存和接受緩存設(shè)置很大也沒有太大提高。后來在對(duì) NetworkStream 讀寫前設(shè)置了緩存,性能一下子提高了很多。

從實(shí)際測試結(jié)果看設(shè)置自己的寫緩存,對(duì)性能的提升最為顯著。我分析了一下,其原因很可能是在向NetworkStream 序列化對(duì)象時(shí),序列化程序調(diào)用了大量的Write 方法向NetworkStream寫入數(shù)據(jù),每次向NetworkStream寫入數(shù)據(jù),數(shù)據(jù)被首先寫入TCP的發(fā)送緩存,并且由調(diào)用線程設(shè)置一個(gè)信號(hào)通知.Net framework 內(nèi)部的TCP線程發(fā)送緩沖區(qū)中已經(jīng)有數(shù)據(jù),TCP線程被激活并讀取發(fā)送緩沖區(qū)中的數(shù)據(jù),組包并向網(wǎng)卡寫入數(shù)據(jù)。頻繁的調(diào)用 NetworkStream.Write 寫入小塊數(shù)據(jù)將導(dǎo)致調(diào)用線程和TCP線程反復(fù)切換,并大量觸發(fā)網(wǎng)卡中斷,導(dǎo)致發(fā)送效率低下。如果我們?cè)诎l(fā)送前將數(shù)據(jù)緩存并按較大的數(shù)據(jù)塊發(fā)送給TCP線程,則大大減少線程切換和網(wǎng)卡中斷數(shù)量,從而大大提高傳輸效率。

問題到這里還沒有結(jié)束,我們發(fā)送的對(duì)象往往較大,如果我們將發(fā)送對(duì)象全部序列化到buffer中再發(fā)送,那么勢必占用大量內(nèi)存,實(shí)際上我們無法忍受這種對(duì)內(nèi)存無限制申請(qǐng)的行為,試想一個(gè)1G大小的對(duì)象,我們?cè)诎l(fā)送前為它另外再開辟1個(gè)G的內(nèi)存來緩存,對(duì)于系統(tǒng)來說簡直是無法忍受。由于我們用.net 發(fā)送數(shù)據(jù),我們?cè)诎l(fā)送時(shí)需要將對(duì)象序列化到流中,而不能像 C/C++那樣直接通過指針來讀取數(shù)據(jù)(當(dāng)然你也可以用unsafe代碼,但這種方式會(huì)帶來其他問題,而且并不為大家所推薦),所以我們需要開發(fā)一個(gè)專門用 TCP 發(fā)送緩存的流來處理讀寫前的緩存。為此我開發(fā)了一個(gè) TcpCacheStream 類,這個(gè)類被用在讀寫 NetworkStream 前先進(jìn)行緩存。

調(diào)用方法很簡單

發(fā)送過程  

  1. object msg;  
  2. //初始化 msg 過程省略  
  3. System.Net.Sockets.NetworkStream _ClientStream;  
  4. //初始化 _ClientStream 過程省略  
  5.    
  6. //創(chuàng)建TcpCacheStream   
  7. TcpCacheStream tcpStream = new TcpCacheStream(_ClientStream);  
  8.    
  9. //二進(jìn)制序列化 msg 對(duì)象到 TcpCacheStream   
  10. IFormatter formatter = new BinaryFormatter();  
  11. formatter.Serialize(tcpStream, msg);  
  12.    
  13. //將緩存中最后一包的數(shù)據(jù)發(fā)送出去  
  14. tcpStream.Flush(); 

接收過程

  1. System.Net.Sockets.NetworkStream _ClientStream;  
  2. //初始化 _ClientStream 過程省略  
  3.    
  4. //創(chuàng)建TcpCacheStream   
  5. TcpCacheStream tcpStream = new TcpCacheStream(_ClientStream);  
  6.    
  7. //從 TcpCacheStream 二進(jìn)制反序列化  
  8. IFormatter formatter = new BinaryFormatter();  
  9. objcet result = formatter.Deserialize(tcpStream); 

TcpCacheStream 類為調(diào)用者封裝了緩存的過程,這個(gè)緩存過程實(shí)際并不復(fù)雜,發(fā)送時(shí)數(shù)據(jù)先寫入TcpCacheStream的buf中,當(dāng)buf滿后才向NetworkStream 寫入數(shù)據(jù),否則只緩存。由于最后一包不能保證正好填滿buf,我們?cè)趯懭霐?shù)據(jù)后一定要調(diào)用 Flush 方法,將所有數(shù)據(jù)都發(fā)送出去。接收的過程反過來,如果buf中沒有數(shù)據(jù),就先將數(shù)據(jù)讀入到buf中,然后再COPY給調(diào)用者,如果已經(jīng)有數(shù)據(jù)則直接COPY給調(diào)用者。

TcpCacheStream 的代碼如下:

  1. [Serializable]  
  2.     public class TcpCacheStream : Stream  
  3.     {  
  4.         #region Private fields  
  5.         const int BUF_SIZE = 4096;  
  6.         private byte[] _Buf = new byte[BUF_SIZE];  
  7.          private MemoryStream _CacheStream = new MemoryStream(BUF_SIZE);  
  8.         private NetworkStream _NetworkStream;  
  9.          private int _BufLen = 0;  
  10.         #endregion  
  11.         #region Private properties  
  12.         private MemoryStream CacheStream  
  13.         {  
  14.             get 
  15.             {  
  16.                 return _CacheStream;  
  17.             }  
  18.         }  
  19.    
  20.         #endregion  
  21.        #region Public properties  
  22.         ///   
  23.         /// get or set the Network Stream  
  24.         ///   
  25.         public NetworkStream NetworkStream  
  26.         {  
  27.             get 
  28.             {  
  29.                 return _NetworkStream;  
  30.             }  
  31.         }  
  32.         #endregion  
  33.         public TcpCacheStream(NetworkStream networkStream)  
  34.         {  
  35.             _NetworkStream = networkStream;  
  36.         }  
  37.         #region Implement stream class  
  38.         public override bool CanRead  
  39.         {  
  40.             get 
  41.             {  
  42.                 return true;  
  43.             }  
  44.         }  
  45.         public override bool CanSeek  
  46.         {  
  47.             get 
  48.             {  
  49.                 return false;  
  50.             }  
  51.         }  
  52.    
  53.         public override bool CanWrite  
  54.         {  
  55.             get 
  56.             {  
  57.                 return true;  
  58.             }  
  59.         }  
  60.          public override void Flush()  
  61.         {  
  62.             NetworkStream.Write(_Buf, 0, _BufLen);  
  63.             NetworkStream.Flush();  
  64.         }  
  65.          public override long Length  
  66.         {  
  67.             get 
  68.             {  
  69.                 throw new Exception("This stream can not seek!");  
  70.             }  
  71.         }  
  72.    
  73.         public override long Position  
  74.         {  
  75.             get 
  76.             {  
  77.                 throw new Exception("This stream can not seek!");  
  78.             }  
  79.    
  80.             set 
  81.             {  
  82.                 throw new Exception("This stream can not seek!");  
  83.             }  
  84.         }  
  85.    
  86.         public override int Read(byte[] buffer, int offset, int count)  
  87.         {  
  88.             int len = 0;  
  89.    
  90.             //If cache is not empty, read from cache  
  91.             if (CacheStream.Length > CacheStream.Position)  
  92.             {  
  93.                 len = CacheStream.Read(buffer, offset, count);  
  94.                 return len;  
  95.             }  
  96.    
  97.             //Fill cache  
  98.             len = NetworkStream.Read(_Buf, 0, BUF_SIZE);  
  99.    
  100.             if (len == 0)  
  101.             {  
  102.                 return 0;  
  103.             }  
  104.    
  105.             CacheStream.Position = 0;  
  106.             CacheStream.Write(_Buf, 0, len);  
  107.             CacheStream.SetLength(len);  
  108.             CacheStream.Position = 0;  
  109.    
  110.             len = CacheStream.Read(buffer, offset, count);  
  111.    
  112.             return len;  
  113.         }  
  114.    
  115.         public override long Seek(long offset, SeekOrigin origin)  
  116.         {  
  117.             throw new Exception("This stream can not seek!");  
  118.         }  
  119.    
  120.         public override void SetLength(long value)  
  121.         {  
  122.             throw new Exception("This stream can not seek!");  
  123.         }  
  124.    
  125.         public override void Write(byte[] buffer, int offset, int count)  
  126.         {  
  127.             if (offset + count > buffer.Length)  
  128.             {  
  129.                 throw new ArgumentException("Count + offset large then buffer.Length");  
  130.             }  
  131.    
  132.             int remain = count - (BUF_SIZE - _BufLen);  
  133.    
  134.             if (remain < 0)  
  135.             {  
  136.                 Array.Copy(buffer, offset, _Buf, _BufLen, count);  
  137.                 _BufLen = BUF_SIZE + remain;  
  138.             }  
  139.             else 
  140.             {  
  141.                 Array.Copy(buffer, offset, _Buf, _BufLen, BUF_SIZE - _BufLen);  
  142.                 NetworkStream.Write(_Buf, 0, _Buf.Length);  
  143.    
  144.                 Array.Copy(buffer, offset + BUF_SIZE - _BufLen, _Buf, 0, remain);  
  145.    
  146.                 _BufLen = remain;  
  147.             }  
  148.         }  
  149.          #endregion  
  150.     } 

原文標(biāo)題:.Net 下通過緩存提高TCP傳輸速度

鏈接:http://www.cnblogs.com/eaglet/archive/2009/11/04/1595887.html

  【責(zé)任編輯:彭凡 TEL:(010)68476606】
責(zé)任編輯:彭凡 來源: 博客園
相關(guān)推薦

2013-03-08 09:57:36

路由器無線傳輸視頻速度

2011-07-04 17:45:45

Qt Sqlite 數(shù)據(jù)庫

2011-02-24 09:42:17

限制傳輸速度

2009-11-09 08:53:21

ASP.NET緩存

2010-07-02 09:25:37

.NET 4.0可擴(kuò)展

2009-08-17 16:34:21

.NET分布式緩存Memcached

2020-04-10 08:55:26

TCPIPBBR算法

2016-09-07 15:02:03

ElasticSear索引速度

2024-06-27 11:00:07

2010-08-30 08:39:27

無線網(wǎng)絡(luò)

2009-02-18 09:42:58

TCPISO傳輸

2024-03-11 15:47:11

RustPython代碼

2011-08-10 15:11:23

SQL Server整理索引碎片重建索引

2010-03-23 09:59:52

無線傳輸速度

2010-10-15 12:39:26

實(shí)際無線傳輸速度

2010-06-17 17:48:05

TCP傳輸控制協(xié)議

2023-10-17 10:11:50

TCPIP

2010-06-09 13:54:13

TCP傳輸協(xié)議

2010-06-09 16:28:50

TCP IP傳輸協(xié)議

2011-05-30 13:15:05

PHP
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)