国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

項(xiàng)目筆記---C#異步Socket示例

2019-11-17 02:43:58
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

項(xiàng)目筆記---C#異步Socket示例

概要

在C#領(lǐng)域或者說(shuō).net通信領(lǐng)域中有著眾多的解決方案,WCF,HttPRequest,WebAPI,Remoting,socket等技術(shù)。這些技術(shù)都有著自己擅長(zhǎng)的領(lǐng)域,或者被合并或者仍然應(yīng)用于某些場(chǎng)合。本文主要介紹Socket通訊,因其有著跨平臺(tái)、跨語(yǔ)言、高性能等優(yōu)勢(shì),適合某些情況的應(yīng)用以及性能優(yōu)越的解決方案。

本文是基于一個(gè)小項(xiàng)目中的應(yīng)用,使用了異步方式的Socket通訊,性能上達(dá)到多客戶端多點(diǎn)通訊,大文件(M-G級(jí)別)的文件傳輸,異步長(zhǎng)連接上的性能優(yōu)勢(shì),但此項(xiàng)目也有些不足:未進(jìn)行大量的外網(wǎng)長(zhǎng)時(shí)間傳輸測(cè)試,對(duì)不穩(wěn)定的網(wǎng)絡(luò)狀況未做很好的處理,例如加入斷點(diǎn)續(xù)傳功能,對(duì)Socket傳輸錯(cuò)誤(其中微軟提供了大量的Socket通訊錯(cuò)誤代碼指示錯(cuò)誤類(lèi)型,請(qǐng)參考http://www.survivalescaperooms.com/Aricc/archive/2010/01/29/1659134.html)未做一個(gè)很好的分類(lèi)處理,只簡(jiǎn)單的統(tǒng)一為一個(gè)類(lèi)型的錯(cuò)誤。所以,此項(xiàng)目介紹只是想拋磚引玉介紹異步Socket通訊,如果有不足或改進(jìn)之處,還請(qǐng)各位不吝指出。

同步和異步區(qū)別

這里的同步和異步指的是服務(wù)端Accept接受客戶端連接請(qǐng)求的方式。在同步模式下,服務(wù)端要開(kāi)啟一個(gè)Thread線程循環(huán)監(jiān)聽(tīng)可能來(lái)自客戶端的服務(wù),如果沒(méi)有則阻塞,如果有連接則接受連接并存入Connection Pool連接池,這樣一個(gè)連接(或者說(shuō)一個(gè)連接線程,一般占用系統(tǒng)內(nèi)存約為2M,具體原因請(qǐng)參考《CLR via C#》中線程章節(jié)),這樣32位系統(tǒng)下單一應(yīng)用程序最大內(nèi)存不超過(guò)2G,也就是說(shuō),單一連接服務(wù)端所能接受客戶端最大的請(qǐng)求數(shù)為1000(實(shí)測(cè)下為700+);而異步連接則應(yīng)用非阻塞式異步連接機(jī)制(http://www.survivalescaperooms.com/2018/archive/2011/05/10/2040333.html)BeginAccept異步接受客戶端請(qǐng)求并執(zhí)行相應(yīng)請(qǐng)求邏輯,在執(zhí)行完畢后系統(tǒng)能自動(dòng)優(yōu)化,并當(dāng)再次應(yīng)用時(shí)喚醒,從而達(dá)到可接受大量的客戶端請(qǐng)求,但也限于“同時(shí)”執(zhí)行的客戶端數(shù)量,對(duì)于某些長(zhǎng)連接客戶端巨大,但并發(fā)性小的情景適用。

自定義協(xié)議

眾所周知,在Socket通訊中傳輸?shù)钠胀ǖ淖址蛘叨M(jìn)制數(shù)據(jù)流,不適用于一些復(fù)雜的情況,例如約定一個(gè)可擴(kuò)展的協(xié)議,可變長(zhǎng)協(xié)議等,所以本項(xiàng)目采用自定義協(xié)議類(lèi)型來(lái)滿足可擴(kuò)展需求:

Header

協(xié)議頭

命令

流1長(zhǎng)度

流2長(zhǎng)度

2字節(jié)

4字節(jié)

4字節(jié)

4字節(jié)

Body

流1

流2

N字節(jié)

N字節(jié)

說(shuō)明:

協(xié)議頭為:FF 7E ,2字節(jié)固定值

命令為:命令編號(hào),如1001

流1長(zhǎng)度:Int32型指示Body中的流1的長(zhǎng)度

流2長(zhǎng)度:Int32型指示Body中的流2的長(zhǎng)度

流1:字節(jié)流

流2:字節(jié)流

這樣,基于上述協(xié)議可自定義流1、流2的長(zhǎng)度分別存放不同數(shù)據(jù),基于協(xié)議還可以對(duì)數(shù)據(jù)協(xié)議進(jìn)行封裝,提供公共的解析方式。

  1     /// <summary>  2     /// 通訊二進(jìn)制協(xié)議,此協(xié)議基于變長(zhǎng)的流傳輸。  3     /// 注:擴(kuò)展此方法成員時(shí),請(qǐng)重寫(xiě)相關(guān)方法。  4     /// </summary>  5     /// <remarks>  6     /// Create By CYS  7     /// </remarks>  8     public class CommunicateProtocol : IDisposable  9     { 10         #region Public Properties 11         /// <summary> 12         /// Byte array length of flag 13         /// </summary> 14         public const int ByteLength_HeaderFlag = 2; 15         /// <summary> 16         /// Byte array length of command 17         /// </summary> 18         public const int ByteLength_HeaderCmd = 4; 19         /// <summary> 20         /// Byte array length of header stream1 21         /// </summary> 22         public const int ByteLength_HeaderStream1Len = 4; 23         /// <summary> 24         /// Byte array length of header stream2 25         /// </summary> 26         public const int ByteLength_HeaderStream2Len = 4; 27         /// <summary> 28         /// 協(xié)議頭長(zhǎng)度 29         /// </summary> 30         public static int FlagLen 31         { 32             get { return ByteLength_HeaderFlag; } 33         } 34         /// <summary> 35         /// 命令(Int32) 36         /// </summary> 37         public int Command 38         { 39             get 40             { 41                 return BitConverter.ToInt32(header_Cmd, 0); 42             } 43             set 44             { 45                 BitConverter.GetBytes(value).CopyTo(header_Cmd, 0); 46             } 47         } 48         /// <summary> 49         /// 流1長(zhǎng)度 50         /// </summary> 51         /// <returns></returns> 52         public int Stream1Len 53         { 54             get 55             { 56                 return BitConverter.ToInt32(header_Stream1Len, 0); 57             } 58             set 59             { 60                 BitConverter.GetBytes(value).CopyTo(header_Stream1Len, 0); 61             } 62         } 63         /// <summary> 64         /// 流2長(zhǎng)度 65         /// </summary> 66         /// <returns></returns> 67         public int Stream2Len 68         { 69             get 70             { 71                 return BitConverter.ToInt32(header_Stream2Len, 0); 72             } 73             set 74             { 75                 BitConverter.GetBytes(value).CopyTo(header_Stream2Len, 0); 76             } 77         } 78         #endregion Public Properties 79  80         #region Private Properties 81         private static byte[] header_Flag = new byte[ByteLength_HeaderFlag]; 82         private byte[] header_Cmd = new byte[ByteLength_HeaderCmd]; 83         private byte[] header_Stream1Len = new byte[ByteLength_HeaderStream1Len]; 84         private byte[] header_Stream2Len = new byte[ByteLength_HeaderStream1Len]; 85         private byte[] body_Stream1 = new byte[0]; 86         private Stream body_Stream2; 87         #endregion Private Properties 88  89         #region Constructor 90         /// <summary> 91         /// Static constructor 92         /// </summary> 93         static CommunicateProtocol() 94         { 95             header_Flag = new byte[ByteLength_HeaderFlag] { 0xFF, 0x7E }; 96         } 97  98         #endregion Constructor 99 100         #region Public Method101         /// <summary>102         /// 判斷是否是協(xié)議頭標(biāo)志103         /// </summary>104         /// <param name="bytes"></param>105         /// <returns></returns>106         public static bool CheckFlag(byte[] bytes)107         {108             if (bytes.Length != header_Flag.Length)109                 return false;110             if (bytes.Length != 2)111                 return false;112             if (!bytes[0].Equals(header_Flag[0]) || !bytes[1].Equals(header_Flag[1]))113                 return false;114             return true;115         }116         /// <summary>117         /// SetStream1118         /// </summary>119         /// <param name="sm"></param>120         public void SetStream1(byte[] sm)121         {122             body_Stream1 = sm;123         }124         /// <summary>125         /// GetStream1126         /// </summary>127         /// <returns></returns>128         public byte[] GetStream1()129         {130             return body_Stream1;131         }132         /// <summary>133         /// SetStream2134         /// </summary>135         /// <param name="sm"></param>136         public void SetStream2(Stream sm)137         {138             body_Stream2 = sm;139         }140         /// <summary>141         /// body_Stream2142         /// </summary>143         /// <returns></returns>144         public Stream GetStream2()145         {146             return body_Stream2;147         }148         /// <summary>149         /// GetHeaderBytes150         /// </summary>151         /// <returns></returns>152         public byte[] GetHeaderBytes()153         {154             int offset = 0;155             byte[] bytes = new byte[ByteLength_HeaderFlag + ByteLength_HeaderCmd + ByteLength_HeaderStream1Len + ByteLength_HeaderStream2Len];156 157             Array.Copy(header_Flag, 0, bytes, 0, ByteLength_HeaderFlag); offset += ByteLength_HeaderFlag;158             Array.Copy(header_Cmd, 0, bytes, offset, ByteLength_HeaderCmd); offset += ByteLength_HeaderCmd;159             Array.Copy(header_Stream1Len, 0, bytes, offset, ByteLength_HeaderStream1Len); offset += ByteLength_HeaderStream1Len;160             Array
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 南城县| 治县。| 长乐市| 西乡县| 赣州市| 健康| 水城县| 滦南县| 抚顺县| 锡林浩特市| 会宁县| 遵化市| 安宁市| 乌鲁木齐市| 莱芜市| 乌拉特中旗| 广丰县| 临猗县| 榆树市| 十堰市| 泊头市| 永安市| 张家界市| 当阳市| 延边| 梁山县| 周口市| 江北区| 磐安县| 卓资县| 奈曼旗| 司法| 来宾市| 会昌县| 高台县| 建瓯市| 大竹县| 南和县| 北川| 津南区| 津南区|