版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、socket開發(fā)之通訊協(xié)議及處理在socket應(yīng)用開發(fā)中,還冇一個(gè)話題是討論的比較多的,那就是數(shù)據(jù)接收后如何處理的 問題。這也是一個(gè)令剛接觸socket開發(fā)的人很頭疼的問題。因?yàn)閟ocket的tcp通訊中有一個(gè)“粘包”的現(xiàn)象,既:人多數(shù)時(shí)候發(fā)送端多次發(fā)送 的小數(shù)據(jù)包會(huì)被連在一起被接收端同時(shí)接收到,多個(gè)小包被組成一個(gè)大包被接收。有時(shí)候一 個(gè)大數(shù)據(jù)包乂會(huì)被拆成多個(gè)小數(shù)據(jù)包發(fā)送。這樣就存在一個(gè)將數(shù)據(jù)包拆分和重新組介的問 題。那么如何去處理這個(gè)問題呢?這就是我今天要講的通訊協(xié)議。所謂的協(xié)議就是通訊雙方協(xié)商并制定好要傳送的數(shù)據(jù)的結(jié)構(gòu)與格式。并按制定好的格式 去組合與分析數(shù)據(jù)。從而使數(shù)據(jù)得以被準(zhǔn)確的理解和
2、處理。那么我們?nèi)绾稳ブ屏⑼ㄓ崊f(xié)議呢?很簡(jiǎn)單,就是指立數(shù)據(jù)中各個(gè)字節(jié)所代表的意義。比 如說:笫一位代表封包頭,笫二位代表封類型,笫三、四位代表封包的數(shù)據(jù)長(zhǎng)度。然后后而 是實(shí)際的數(shù)據(jù)內(nèi)容。如卜面這個(gè)例子:010106 0001 of ef 87 56 34協(xié)議類別協(xié)議代碼數(shù)據(jù)長(zhǎng)度實(shí)際數(shù)據(jù)前面三部分稱z為封包頭,它的長(zhǎng)度是固定的,第四部分定封包數(shù)據(jù),它的長(zhǎng)度是不固 定的,由笫三部分標(biāo)識(shí)其長(zhǎng)度。因?yàn)槲覀兊膮f(xié)議將川在tcp屮,所以我沒有加入校驗(yàn)位。 原因是tcp nj以保證數(shù)據(jù)的完整性。校驗(yàn)位是沒有必要存在的。接下來我們要為這個(gè)數(shù)據(jù)封包聲明一個(gè)類來封裝它:3 i1 public class messag
3、e private byte _class;private byte _flag;private int _size;private byte .content;89訥10白由11弭12 -13 i1415弭16抽17艸18 -192021艸22帥23艸24 i-25 i26 i27艸28艸29昇30卜3132 i33弭34 i35卜36 i37public byte contentget return _content; set _content = value; public int sizeget return _size; set _size = value; public byte
4、flagget return _flag; set _flag = value; public byte classget return _class; set class = value; public message()public message(byte ©class, byte flag, bytc content)class = c1ass;flag = flag;_sizecontent length;_content = content;public byte tobytes()byte _byte;using (memorystream mem = new memo
5、rystream()binarywriter writer = new binarywriter(mem); writer write(_class);writer. write(_flag);writer. write(一size);if (_size > 0)writer. write(_content);_bytc = mom .toarrayo; writer. close();return _byte;public static message erombytes(byte buffer)message message = new message();using (memory
6、stream mem = new memorystream(buffer)68抑69 1binaryreader reader = new binaryreader(mem);70message, class = readerreadbyte();71message _flagreader readbyte();72 1message. _size = reader.rcadlnt32();73 1if (message. _sizc > 0)74軸75message content = reader. readbytes(message .size);76 k77reader. clo
7、se ();78 k79 1return message;80卜8182 l 我們可以用tobytes()和frombytes()將封包轉(zhuǎn)換成二進(jìn)制數(shù)組和從二進(jìn)制數(shù)組轉(zhuǎn)換 回來。事情看起來已經(jīng)解決了,但真的是這樣子嗎?不然,我們知道,tcp數(shù)據(jù)是以流 的形式被傳送的,我們并不知道一個(gè)數(shù)據(jù)包是否被傳送完畢,也不知道我們接收冋來的數(shù)據(jù) 包中是否有多個(gè)數(shù)據(jù)包,如果百接使用frombytes()來轉(zhuǎn)換的話,很門j能會(huì)因?yàn)閿?shù)據(jù)不完 整而出現(xiàn)杲常,也有可能會(huì)因?yàn)閿?shù)據(jù)中含有多個(gè)數(shù)據(jù)包而導(dǎo)致數(shù)據(jù)丟失(因?yàn)槟悴⒉恢肋@ 些數(shù)據(jù)小含冇多少個(gè)數(shù)據(jù)包)。那我們?cè)撛趺崔k?這也不難,我們先把接收回來的數(shù)據(jù)寫入 一個(gè)流屮。
8、然后分析其屮是否有完整的數(shù)據(jù)包,如果有,將其從流屮取出,并將這部分?jǐn)?shù)據(jù) 從流中清除。直到流中沒有完整的數(shù)據(jù)為止,以厲接收冋來的數(shù)據(jù)就將其寫入流的結(jié)尾處, 并從頭繼續(xù)分析。直到結(jié)束。讓我們來看看這部分的代碼:aa1 public class messagestrcamprivate byte buffer; private int position; private int _length; private int capacity;public messagestream()_buffer new byte0;_position = 0;_length = 0;capac ity 二();pr
9、ivate byte readbyte()if (this. position >二 this. length)return 0;return this. _buffcrthis. _position+;private int readlnt()int num = this.position +二 4;if (num > this. length)this._position = this. _length;return t;32卜33return (this, buffernum - 4 | (this, buffernum - 3 < < 8) | (this, b
10、uffernum - 2 « 0x10) | (this, buffernum - 1 << 0x18);34卜3536 i3泊由38 i39 i40自申41 i42 i-4344#4546卜47 i48 i49肖由50 i51 i52申由53 i54卜55 i-56 i57申由58 i59 i-60 iprivate bytc rcadbytcs(int, count)int num 二 this. length - this. position;if (num > count)(num = count;if (num <= 0)return null;by
11、te buffer = new bytenum;if (num <= 8)int num2 = num;while (num2 >= 0)buffer num2 = this, buffer this, pos ition + nun)2;elsebuffer. blockcopy (this, buffer, this, position, buffer, 0, num);this. _position +二 num;61 i62卜63 i64 i65申由66 i67 i68 i69目由70 i71 i72 i73 i74 i75艸76 i7泊由78 i79卜80 i81 i82
12、 preturn buffer;public bool read(out message message)message = null;position 二 0;if (length > 6)message = new message ();message. class = readbyte 0:message. flag = readbyte();message. size = readlnt ();if (message .size <= 0 | message .size <= _length 一 _position) if (message. size > 0)
13、message. content = readbytes(message. size);remove(message. size + 6);return true;8384目由8586 i87 |-88卜89 ielsemessage = null;return false;91 ireturn false;92卜93 i"94 i95private void ensurecapacity(int value)96抽97 iif (value <= this. _capacity)98 ireturn;99 iint numl = value;100 iif (numl <
14、; 0x100)101 inuml = 0x100;102 iif (numl < (this, capacity * 2)103 numl = this, capacity * 2;104 byte bufferl new bytenuml:105106 i107 i108 i109卜110 iml112申由if (this. _length > 0)buffer. blockcopy (this. _buffcr, 0, bufferl, 0, this. _lcngth);this, buffer = bufferl;this, capacity = numl;public
15、void writc(byte buffer, int offset, int count)11311泊由if (buffer length - offset < count)115 count = buffer .length - offset;116 卜 117 iensurecapacity(buffer. length + count);118 iarray.clear( buffer, length, capacity - length);119 buffer. blockcopy(buffer, offset, _buffer, _length, count);120 i_l
16、cngth += count;121卜122123 1private void remove(int count)12泊由125if (_length >= count)126白由127buffer. blockcopy( buffer, count, buffer, 0, length - count);128 1length -二 count;129 1array. clear(_buffer, _length, _capacity - _length);130 1-丨else132申由133 1length = 0;134 1array. clear(_buffer, 0, _ca
17、pacity);135卜136卜137 1-這個(gè)類的使用非常簡(jiǎn)單,你只要用write (byte buffer, int offset, int count)將接收至!j 的數(shù)據(jù)寫入數(shù)據(jù)流屮,并用bool read (out message message)將數(shù)據(jù)屮的第一個(gè)數(shù)據(jù)包取出, 如果函數(shù)返冋true,就說明取冋一個(gè)封包成功,如果返冋false,則說明流中己經(jīng)沒有完 整的封包,你需要繼續(xù)接收后面的數(shù)據(jù)以組成一個(gè)完整的封包。這們我們的數(shù)據(jù)分析就會(huì)變得非常簡(jiǎn)單。我們可以在receivecallback回調(diào)函數(shù)中將 接收到的數(shù)據(jù)寫入到流中并通知線程池中的工作者線程分析數(shù)據(jù)流并處理數(shù)據(jù)。我在前面的 關(guān)于socket異步操
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 倉(cāng)庫(kù)擴(kuò)大補(bǔ)充協(xié)議書
- 第9課-2023-2024學(xué)年初中信息技術(shù)七年級(jí)上冊(cè)(人教版)-說課稿-制作電子表格
- 變更扶養(yǎng)協(xié)議書
- 北京房屋租賃合同2008
- 防火應(yīng)急疏散演練幼兒園
- 天津市南開區(qū)2024-2025學(xué)年高一上學(xué)期11月期中考試語(yǔ)文試題(含答案)
- 遼寧省錦州市某校2024-2025學(xué)年高二上學(xué)期期中質(zhì)量檢測(cè)英語(yǔ)試卷(無答案)
- 糖尿病的演講
- 《纖維繩索彎曲疲勞試驗(yàn)方法》
- 飼料級(jí)磷酸鹽相關(guān)項(xiàng)目投資計(jì)劃書范本
- 北師大版七年級(jí)生物上冊(cè)教案(全冊(cè)完整版)
- 家禽常見用藥的技巧課件
- 防腐油漆施工工藝
- 南方S82T操作手冊(cè)
- 設(shè)備采購(gòu)安裝工程結(jié)算書
- [精品]臺(tái)灣地區(qū)零售藥店的現(xiàn)狀與發(fā)展趨勢(shì)
- 焙燒爐煙氣換熱器的設(shè)計(jì)方案
- 中學(xué)語(yǔ)文學(xué)科課改實(shí)驗(yàn)匯報(bào)材料
- 血漿置換及臨床的應(yīng)用業(yè)內(nèi)特制
- 雨蝶(李翊君)原版正譜鋼琴譜五線譜樂譜.docx
- 綜合實(shí)踐活動(dòng)五年級(jí)下冊(cè)課件-制作木蜻蜓14張ppt課件
評(píng)論
0/150
提交評(píng)論