您好,登錄后才能下訂單哦!
小編給大家分享一下socket如何傳輸protobuf字節流,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
首先的拼接數據包
1 /// <summary> 2 /// 構建消息數據包 3 /// </summary> 4 /// <param name="protobufModel"></param> 5 byte[] BuildPackage(IExtensible protobufModel) 6 { 7 if (protobufModel != null) 8 { 9 byte[] b = ProtobufSerilizer.Serialize(protobufModel);10 11 ByteBuffer buf = ByteBuffer.Allocate(b.Length + 4);12 buf.WriteInt(b.Length);13 buf.WriteBytes(b);14 return buf.GetBytes();15 }16 return null;17 }
代碼中使用的ByteBuffer工具java中有提供,但是c#中是沒有的,源碼摘至,不過作者并未在工具中添加獲取所有字節碼的方法,所以自己添加了一個GetBytes()方法
1 using System; 2 using System.Collections.Generic; 3 4 /// <summary> 5 /// 字節緩沖處理類,本類僅處理大字節序 6 /// 警告,本類非線程安全 7 /// </summary> 8 public class ByteBuffer 9 { 10 //字節緩存區 11 private byte[] buf; 12 //讀取索引 13 private int readIndex = 0; 14 //寫入索引 15 private int writeIndex = 0; 16 //讀取索引標記 17 private int markReadIndex = 0; 18 //寫入索引標記 19 private int markWirteIndex = 0; 20 //緩存區字節數組的長度 21 private int capacity; 22 23 //對象池 24 private static List<ByteBuffer> pool = new List<ByteBuffer>(); 25 private static int poolMaxCount = 200; 26 //此對象是否池化 27 private bool isPool = false; 28 29 /// <summary> 30 /// 構造方法 31 /// </summary> 32 /// <param name="capacity">初始容量</param> 33 private ByteBuffer(int capacity) 34 { 35 buf = new byte[capacity]; 36 this.capacity = capacity; 37 } 38 39 /// <summary> 40 /// 構造方法 41 /// </summary> 42 /// <param name="bytes">初始字節數組</param> 43 private ByteBuffer(byte[] bytes) 44 { 45 buf = bytes; 46 this.capacity = bytes.Length; 47 this.readIndex = 0; 48 this.writeIndex = bytes.Length + 1; 49 } 50 51 /// <summary> 52 /// 構建一個capacity長度的字節緩存區ByteBuffer對象 53 /// </summary> 54 /// <param name="capacity">初始容量</param> 55 /// <returns>ByteBuffer對象</returns> 56 public static ByteBuffer Allocate(int capacity) 57 { 58 return new ByteBuffer(capacity); 59 } 60 61 /// <summary> 62 /// 構建一個以bytes為字節緩存區的ByteBuffer對象,一般不推薦使用 63 /// </summary> 64 /// <param name="bytes">初始字節數組</param> 65 /// <returns>ByteBuffer對象</returns> 66 public static ByteBuffer Allocate(byte[] bytes) 67 { 68 return new ByteBuffer(bytes); 69 } 70 71 /// <summary> 72 /// 獲取一個池化的ByteBuffer對象,池化的對象必須在調用Dispose后才會推入池中,否則此方法等同于Allocate(int capacity)方法,此方法為線程安全的 73 /// </summary> 74 /// <param name="capacity">ByteBuffer對象的初始容量大小,如果緩存池中沒有對象,則對象的容量大小為此值,否則為池中對象的實際容量值</param> 75 /// <returns></returns> 76 public static ByteBuffer GetFromPool(int capacity) 77 { 78 lock (pool) 79 { 80 ByteBuffer bbuf; 81 if (pool.Count == 0) 82 { 83 bbuf = Allocate(capacity); 84 bbuf.isPool = true; 85 return bbuf; 86 } 87 int lastIndex = pool.Count - 1; 88 bbuf = pool[lastIndex]; 89 pool.RemoveAt(lastIndex); 90 if (!bbuf.isPool) 91 { 92 bbuf.isPool = true; 93 } 94 return bbuf; 95 } 96 } 97 98 /// <summary> 99 /// 根據length長度,確定大于此leng的最近的2次方數,如length=7,則返回值為8100 /// </summary>101 /// <param name="length">參考容量</param>102 /// <returns>比參考容量大的最接近的2次方數</returns>103 private int FixLength(int length)104 {105 int n = 2;106 int b = 2;107 while (b < length)108 {109 b = 2 << n;110 n++;111 }112 return b;113 }114 115 /// <summary>116 /// 翻轉字節數組,如果本地字節序列為低字節序列,則進行翻轉以轉換為高字節序列117 /// </summary>118 /// <param name="bytes">待轉為高字節序的字節數組</param>119 /// <returns>高字節序列的字節數組</returns>120 private byte[] flip(byte[] bytes)121 {122 if (BitConverter.IsLittleEndian)123 {124 Array.Reverse(bytes);125 }126 return bytes;127 }128 129 /// <summary>130 /// 確定內部字節緩存數組的大小131 /// </summary>132 /// <param name="currLen">當前容量</param>133 /// <param name="futureLen">將來的容量</param>134 /// <returns>將來的容量</returns>135 private int FixSizeAndReset(int currLen, int futureLen)136 {137 if (futureLen > currLen)138 {139 //以原大小的2次方數的兩倍確定內部字節緩存區大小140 int size = FixLength(currLen) * 2;141 if (futureLen > size)142 {143 //以將來的大小的2次方的兩倍確定內部字節緩存區大小144 size = FixLength(futureLen) * 2;145 }146 byte[] newbuf = new byte[size];147 Array.Copy(buf, 0, newbuf, 0, currLen);148 buf = newbuf;149 capacity = newbuf.Length;150 }151 return futureLen;152 }153 154 /// <summary>155 /// 將bytes字節數組從startIndex開始的length字節寫入到此緩存區156 /// </summary>157 /// <param name="bytes">待寫入的字節數據</param>158 /// <param name="startIndex">寫入的開始位置</param>159 /// <param name="length">寫入的長度</param>160 public void WriteBytes(byte[] bytes, int startIndex, int length)161 {162 int offset = length - startIndex;163 if (offset <= 0) return;164 int total = offset + writeIndex;165 int len = buf.Length;166 FixSizeAndReset(len, total);167 for (int i = writeIndex, j = startIndex; i < total; i++, j++)168 {169 buf[i] = bytes[j];170 }171 writeIndex = total;172 }173 174 /// <summary>175 /// 將字節數組中從0到length的元素寫入緩存區176 /// </summary>177 /// <param name="bytes">待寫入的字節數據</param>178 /// <param name="length">寫入的長度</param>179 public void WriteBytes(byte[] bytes, int length)180 {181 WriteBytes(bytes, 0, length);182 }183 184 /// <summary>185 /// 將字節數組全部寫入緩存區186 /// </summary>187 /// <param name="bytes">待寫入的字節數據</param>188 public void WriteBytes(byte[] bytes)189 {190 WriteBytes(bytes, bytes.Length);191 }192 193 /// <summary>194 /// 將一個ByteBuffer的有效字節區寫入此緩存區中195 /// </summary>196 /// <param name="buffer">待寫入的字節緩存區</param>197 public void Write(ByteBuffer buffer)198 {199 if (buffer == null) return;200 if (buffer.ReadableBytes() <= 0) return;201 WriteBytes(buffer.ToArray());202 }203 204 /// <summary>205 /// 寫入一個int16數據206 /// </summary>207 /// <param name="value">short數據</param>208 public void WriteShort(short value)209 {210 WriteBytes(flip(BitConverter.GetBytes(value)));211 }212 213 /// <summary>214 /// 寫入一個ushort數據215 /// </summary>216 /// <param name="value">ushort數據</param>217 public void WriteUshort(ushort value)218 {219 WriteBytes(flip(BitConverter.GetBytes(value)));220 }221 222 /// <summary>223 /// 寫入一個int32數據224 /// </summary>225 /// <param name="value">int數據</param>226 public void WriteInt(int value)227 {228 //byte[] array = new byte[4];229 //for (int i = 3; i >= 0; i--)230 //{231 // array[i] = (byte)(value & 0xff);232 // value = value >> 8;233 //}234 //Array.Reverse(array);235 //Write(array);236 WriteBytes(flip(BitConverter.GetBytes(value)));237 }238 239 /// <summary>240 /// 寫入一個uint32數據241 /// </summary>242 /// <param name="value">uint數據</param>243 public void WriteUint(uint value)244 {245 WriteBytes(flip(BitConverter.GetBytes(value)));246 }247 248 /// <summary>249 /// 寫入一個int64數據250 /// </summary>251 /// <param name="value">long數據</param>252 public void WriteLong(long value)253 {254 WriteBytes(flip(BitConverter.GetBytes(value)));255 }256 257 /// <summary>258 /// 寫入一個uint64數據259 /// </summary>260 /// <param name="value">ulong數據</param>261 public void WriteUlong(ulong value)262 {263 WriteBytes(flip(BitConverter.GetBytes(value)));264 }265 266 /// <summary>267 /// 寫入一個float數據268 /// </summary>269 /// <param name="value">float數據</param>270 public void WriteFloat(float value)271 {272 WriteBytes(flip(BitConverter.GetBytes(value)));273 }274 275 /// <summary>276 /// 寫入一個byte數據277 /// </summary>278 /// <param name="value">byte數據</param>279 public void WriteByte(byte value)280 {281 int afterLen = writeIndex + 1;282 int len = buf.Length;283 FixSizeAndReset(len, afterLen);284 buf[writeIndex] = value;285 writeIndex = afterLen;286 }287 288 /// <summary>289 /// 寫入一個byte數據290 /// </summary>291 /// <param name="value">byte數據</param>292 public void WriteByte(int value)293 {294 byte b = (byte)value;295 WriteByte(b);296 }297 298 /// <summary>299 /// 寫入一個double類型數據300 /// </summary>301 /// <param name="value">double數據</param>302 public void WriteDouble(double value)303 {304 WriteBytes(flip(BitConverter.GetBytes(value)));305 }306 307 /// <summary>308 /// 寫入一個字符309 /// </summary>310 /// <param name="value"></param>311 public void WriteChar(char value)312 {313 WriteBytes(flip(BitConverter.GetBytes(value)));314 }315 316 /// <summary>317 /// 寫入一個布爾型數據318 /// </summary>319 /// <param name="value"></param>320 public void WriteBoolean(bool value)321 {322 WriteBytes(flip(BitConverter.GetBytes(value)));323 }324 325 /// <summary>326 /// 讀取一個字節327 /// </summary>328 /// <returns>字節數據</returns>329 public byte ReadByte()330 {331 byte b = buf[readIndex];332 readIndex++;333 return b;334 }335 336 /// <summary>337 /// 讀取一個字節并轉為int類型的數據338 /// </summary>339 /// <returns>int數據</returns>340 public int ReadByteToInt()341 {342 byte b = ReadByte();343 return (int)b;344 }345 346 /// <summary>347 /// 獲取從index索引處開始len長度的字節348 /// </summary>349 /// <param name="index"></param>350 /// <param name="len"></param>351 /// <returns></returns>352 private byte[] Get(int index, int len)353 {354 byte[] bytes = new byte[len];355 Array.Copy(buf, index, bytes, 0, len);356 return flip(bytes);357 }358 359 /// <summary>360 /// 從讀取索引位置開始讀取len長度的字節數組361 /// </summary>362 /// <param name="len">待讀取的字節長度</param>363 /// <returns>字節數組</returns>364 private byte[] Read(int len)365 {366 byte[] bytes = Get(readIndex, len);367 readIndex += len;368 return bytes;369 }370 371 /// <summary>372 /// 讀取一個uint16數據373 /// </summary>374 /// <returns>ushort數據</returns>375 public ushort ReadUshort()376 {377 return BitConverter.ToUInt16(Read(2), 0);378 }379 380 /// <summary>381 /// 讀取一個int16數據382 /// </summary>383 /// <returns>short數據</returns>384 public short ReadShort()385 {386 return BitConverter.ToInt16(Read(2), 0);387 }388 389 /// <summary>390 /// 讀取一個uint32數據391 /// </summary>392 /// <returns>uint數據</returns>393 public uint ReadUint()394 {395 return BitConverter.ToUInt32(Read(4), 0);396 }397 398 /// <summary>399 /// 讀取一個int32數據400 /// </summary>401 /// <returns>int數據</returns>402 public int ReadInt()403 {404 return BitConverter.ToInt32(Read(4), 0);405 }406 407 /// <summary>408 /// 讀取一個uint64數據409 /// </summary>410 /// <returns>ulong數據</returns>411 public ulong ReadUlong()412 {413 return BitConverter.ToUInt64(Read(8), 0);414 }415 416 /// <summary>417 /// 讀取一個long數據418 /// </summary>419 /// <returns>long數據</returns>420 public long ReadLong()421 {422 return BitConverter.ToInt64(Read(8), 0);423 }424 425 /// <summary>426 /// 讀取一個float數據427 /// </summary>428 /// <returns>float數據</returns>429 public float ReadFloat()430 {431 return BitConverter.ToSingle(Read(4), 0);432 }433 434 /// <summary>435 /// 讀取一個double數據436 /// </summary>437 /// <returns>double數據</returns>438 public double ReadDouble()439 {440 return BitConverter.ToDouble(Read(8), 0);441 }442 443 /// <summary>444 /// 讀取一個字符445 /// </summary>446 /// <returns></returns>447 public char ReadChar()448 {449 return BitConverter.ToChar(Read(2), 0);450 }451 452 /// <summary>453 /// 讀取布爾型數據454 /// </summary>455 /// <returns></returns>456 public bool ReadBoolean()457 {458 return BitConverter.ToBoolean(Read(1), 0);459 }460 461 /// <summary>462 /// 從讀取索引位置開始讀取len長度的字節到disbytes目標字節數組中463 /// </summary>464 /// <param name="disbytes">讀取的字節將存入此字節數組</param>465 /// <param name="disstart">目標字節數組的寫入索引</param>466 /// <param name="len">讀取的長度</param>467 public void ReadBytes(byte[] disbytes, int disstart, int len)468 {469 int size = disstart + len;470 for (int i = disstart; i < size; i++)471 {472 disbytes[i] = this.ReadByte();473 }474 }475 476 /// <summary>477 /// 獲取一個字節478 /// </summary>479 /// <param name="index"></param>480 /// <returns></returns>481 public byte GetByte(int index)482 {483 return buf[index];484 }485 486 /// <summary>487 /// 獲取全部字節488 /// </summary>489 /// <returns></returns>490 public byte[] GetBytes()491 {492 return buf;493 }494 495 /// <summary>496 /// 獲取一個雙精度浮點數據,不改變數據內容497 /// </summary>498 /// <param name="index">字節索引</param>499 /// <returns></returns>500 public double GetDouble(int index)501 {502 return BitConverter.ToDouble(Get(0, 8), 0);503 }504 505 /// <summary>506 /// 獲取一個浮點數據,不改變數據內容507 /// </summary>508 /// <param name="index">字節索引</param>509 /// <returns></returns>510 public float GetFloat(int index)511 {512 return BitConverter.ToSingle(Get(0, 4), 0);513 }514 515 /// <summary>516 /// 獲取一個長整形數據,不改變數據內容517 /// </summary>518 /// <param name="index">字節索引</param>519 /// <returns></returns>520 public long GetLong(int index)521 {522 return BitConverter.ToInt64(Get(0, 8), 0);523 }524 525 /// <summary>526 /// 獲取一個整形數據,不改變數據內容527 /// </summary>528 /// <param name="index">字節索引</param>529 /// <returns></returns>530 public int GetInt(int index)531 {532 return BitConverter.ToInt32(Get(0, 4), 0);533 }534 535 /// <summary>536 /// 獲取一個短整形數據,不改變數據內容537 /// </summary>538 /// <param name="index">字節索引</param>539 /// <returns></returns>540 public int GetShort(int index)541 {542 return BitConverter.ToInt16(Get(0, 2), 0);543 }544 545 546 /// <summary>547 /// 清除已讀字節并重建緩存區548 /// </summary>549 public void DiscardReadBytes()550 {551 if (readIndex <= 0) return;552 int len = buf.Length - readIndex;553 byte[] newbuf = new byte[len];554 Array.Copy(buf, readIndex, newbuf, 0, len);555 buf = newbuf;556 writeIndex -= readIndex;557 markReadIndex -= readIndex;558 if (markReadIndex < 0)559 {560 markReadIndex = readIndex;561 }562 markWirteIndex -= readIndex;563 if (markWirteIndex < 0 || markWirteIndex < readIndex || markWirteIndex < markReadIndex)564 {565 markWirteIndex = writeIndex;566 }567 readIndex = 0;568 }569 570 /// <summary>571 /// 清空此對象,但保留字節緩存數組(空數組)572 /// </summary>573 public void Clear()574 {575 buf = new byte[buf.Length];576 readIndex = 0;577 writeIndex = 0;578 markReadIndex = 0;579 markWirteIndex = 0;580 capacity = buf.Length;581 }582 583 /// <summary>584 /// 釋放對象,清除字節緩存數組,如果此對象為可池化,那么調用此方法將會把此對象推入到池中等待下次調用585 /// </summary>586 public void Dispose()587 {588 readIndex = 0;589 writeIndex = 0;590 markReadIndex = 0;591 markWirteIndex = 0;592 if (isPool)593 {594 lock (pool)595 {596 if (pool.Count < poolMaxCount)597 {598 pool.Add(this);599 }600 }601 }602 else603 {604 capacity = 0;605 buf = null;606 }607 }608 609 /// <summary>610 /// 設置/獲取讀指針位置611 /// </summary>612 public int ReaderIndex613 {614 get615 {616 return readIndex;617 }618 set619 {620 if (value < 0) return;621 readIndex = value;622 }623 }624 625 /// <summary>626 /// 設置/獲取寫指針位置627 /// </summary>628 public int WriterIndex629 {630 get631 {632 return writeIndex;633 }634 set635 {636 if (value < 0) return;637 writeIndex = value;638 }639 }640 641 /// <summary>642 /// 標記讀取的索引位置643 /// </summary>644 public void MarkReaderIndex()645 {646 markReadIndex = readIndex;647 }648 649 /// <summary>650 /// 標記寫入的索引位置651 /// </summary>652 public void MarkWriterIndex()653 {654 markWirteIndex = writeIndex;655 }656 657 /// <summary>658 /// 將讀取的索引位置重置為標記的讀取索引位置659 /// </summary>660 public void ResetReaderIndex()661 {662 readIndex = markReadIndex;663 }664 665 /// <summary>666 /// 將寫入的索引位置重置為標記的寫入索引位置667 /// </summary>668 public void ResetWriterIndex()669 {670 writeIndex = markWirteIndex;671 }672 673 /// <summary>674 /// 可讀的有效字節數675 /// </summary>676 /// <returns>可讀的字節數</returns>677 public int ReadableBytes()678 {679 return writeIndex - readIndex;680 }681 682 /// <summary>683 /// 獲取可讀的字節數組684 /// </summary>685 /// <returns>字節數據</returns>686 public byte[] ToArray()687 {688 byte[] bytes = new byte[writeIndex];689 Array.Copy(buf, 0, bytes, 0, bytes.Length);690 return bytes;691 }692 693 /// <summary>694 /// 獲取緩存區容量大小695 /// </summary>696 /// <returns>緩存區容量</returns>697 public int GetCapacity()698 {699 return this.capacity;700 }701 702 /// <summary>703 /// 簡單的數據類型704 /// </summary>705 public enum LengthType706 {707 //byte類型708 BYTE,709 //short類型710 SHORT,711 //int類型712 INT713 }714 715 /// <summary>716 /// 寫入一個數據717 /// </summary>718 /// <param name="value">待寫入的數據</param>719 /// <param name="type">待寫入的數據類型</param>720 public void WriteValue(int value, LengthType type)721 {722 switch (type)723 {724 case LengthType.BYTE:725 this.WriteByte(value);726 break;727 case LengthType.SHORT:728 this.WriteShort((short)value);729 break;730 default:731 this.WriteInt(value);732 break;733 }734 }735 736 /// <summary>737 /// 讀取一個值,值類型根據type決定,int或short或byte738 /// </summary>739 /// <param name="type">值類型</param>740 /// <returns>int數據</returns>741 public int ReadValue(LengthType type)742 {743 switch (type)744 {745 case LengthType.BYTE:746 return ReadByteToInt();747 case LengthType.SHORT:748 return (int)ReadShort();749 default:750 return ReadInt();751 }752 }753 754 /// <summary>755 /// 寫入一個字符串756 /// </summary>757 /// <param name="content">待寫入的字符串</param>758 /// <param name="lenType">寫入的字符串長度類型</param>759 public void WriteUTF8String(string content, LengthType lenType)760 {761 byte[] bytes = System.Text.UTF8Encoding.UTF8.GetBytes(content);762 int max;763 if (lenType == LengthType.BYTE)764 {765 WriteByte(bytes.Length);766 max = byte.MaxValue;767 }768 else if (lenType == LengthType.SHORT)769 {770 WriteShort((short)bytes.Length);771 max = short.MaxValue;772 }773 else774 {775 WriteInt(bytes.Length);776 max = int.MaxValue;777 }778 if (bytes.Length > max)779 {780 WriteBytes(bytes, 0, max);781 }782 else783 {784 WriteBytes(bytes, 0, bytes.Length);785 }786 }787 788 /// <summary>789 /// 讀取一個字符串790 /// </summary>791 /// <param name="len">需讀取的字符串長度</param>792 /// <returns>字符串</returns>793 public string ReadUTF8String(int len)794 {795 byte[] bytes = new byte[len];796 this.ReadBytes(bytes, 0, len);797 return System.Text.UTF8Encoding.UTF8.GetString(bytes);798 }799 800 /// <summary>801 /// 讀取一個字符串802 /// </summary>803 /// <param name="lenType">字符串長度類型</param>804 /// <returns>字符串</returns>805 public string ReadUTF8String(LengthType lenType)806 {807 int len = ReadValue(lenType);808 return ReadUTF8String(len);809 }810 811 /// <summary>812 /// 復制一個對象,具有與原對象相同的數據,不改變原對象的數據813 /// </summary>814 /// <returns></returns>815 public ByteBuffer Copy()816 {817 return Copy(0);818 }819 820 public ByteBuffer Copy(int startIndex)821 {822 if (buf == null)823 {824 return new ByteBuffer(16);825 }826 byte[] target = new byte[buf.Length - startIndex];827 Array.Copy(buf, startIndex, target, 0, target.Length);828 ByteBuffer buffer = new ByteBuffer(target.Length);829 buffer.WriteBytes(target);830 return buffer;831 }832 }
View Code
當然,c#中雖然沒有ByteBuffer,但也有拼接字節數組的方法,比如
Send( [] bytes = [data.Length + [] length = BitConverter.GetBytes( Array.Copy(length, , bytes, , Array.Copy(data, , bytes, mSocket.Send(bytes); }
字節數組拼接好后,就可以使用socket的send方法發送了,不過這一篇先繼續講完接收數據的處理
接收數據的順序是先接收消息長度,然后根據消息長度接收指定長度的消息
1 void ReceiveMessage() 2 { 3 //上文說過,一個完整的消息是 消息長度+消息內容 4 //所以先創建一個長度4的字節數組,用于接收消息長度 5 byte[] recvBytesHead = GetBytesReceive(4); 6 //將消息長度字節組轉為int數值 7 int bodyLength = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(recvBytesHead, 0)); 8 //根據消息長度接收指定長度的字節組,這個字節組就是完整的消息內容 9 byte[] recvBytesBody = GetBytesReceive(bodyLength);10 //最后反序列化消息的內容11 Test message = ProtobufSerilizer.DeSerialize<Test>(messageBody);12 }
GetBytesRecive方法用于接收消息,并解決粘包、少包的問題,代碼如下
1 /// <summary> 2 /// 接收數據并處理 3 /// </summary> 4 /// <param name="length"></param> 5 /// <returns></returns> 6 byte[] GetBytesReceive(int length) 7 { 8 //創建指定長度的字節組 9 byte[] recvBytes = new byte[length];10 //設置每次接收包的最大長度為1024個字節11 int packageMaxLength = 1024;12 //使用循環來保證接收的數據是完整的,如果剩余長度大于0,證明接收未完成13 while (length > 0)14 {15 //創建字節組,用于存放需要接收的字節流16 byte[] receiveBytes = new byte[length < packageMaxLength ? length : packageMaxLength];17 int iBytesBody = 0;18 //根據剩余需接收的長度來設置接收數據的長度19 if (length >= receiveBytes.Length)20 iBytesBody = mSocket.Receive(receiveBytes, receiveBytes.Length, 0);21 else22 iBytesBody = mSocket.Receive(receiveBytes, length, 0);23 receiveBytes.CopyTo(recvBytes, recvBytes.Length - length);24 //減去已接收的長度25 length -= iBytesBody;26 }27 return recvBytes;28 }
到這里,消息的簡單發送和接收就基本搞定了,但是,實際項目中,我們的消息數量肯定不會只有一條,如果是長鏈接的項目,更是需要一直接收和發送消息,該怎么辦?
unity的UI上的顯示只能在主線程中執行,可是如果我們在主線程一直接收和發送消息,那體驗將會極差,所以我們必須另外開啟線程來負責消息的接收和發送。
以上是“socket如何傳輸protobuf字節流”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。