看了系列一 我們開啟了對socket tcp的監(jiān)聽狀態(tài),那么這一章我們來講解怎么創(chuàng)建socket的通信代碼
我新建一個(gè)類TSocketBase
1 public abstract class TSocketBase 2 { 3 //封裝socket 4 internal Socket _Socket; 5 //回調(diào) 6 PRivate AsyncCallback aCallback; 7 //接受數(shù)據(jù)的緩沖區(qū) 8 private byte[] Buffers; 9 //標(biāo)識是否已經(jīng)釋放 10 private volatile bool IsDispose; 11 //10K的緩沖區(qū)空間 12 private int BufferSize = 10 * 1024; 13 //收取消息狀態(tài)碼 14 private SocketError ReceiveError; 15 //發(fā)送消息的狀態(tài)碼 16 private SocketError SenderError; 17 //每一次接受到的字節(jié)數(shù) 18 private int ReceiveSize = 0; 19 //接受空消息次數(shù) 20 byte ZeroCount = 0; 21 22 public abstract void Receive(byte[] rbuff); 23 24 public void SetSocket() 25 { 26 this.aCallback = new AsyncCallback(this.ReceiveCallback); 27 this.IsDispose = false; 28 this._Socket.ReceiveBufferSize = this.BufferSize; 29 this._Socket.SendBufferSize = this.BufferSize; 30 this.Buffers = new byte[this.BufferSize]; 31 } 32 33 34 /// <summary> 35 /// 關(guān)閉并釋放資源 36 /// </summary> 37 /// <param name="msg"></param> 38 public void Close(string msg) 39 { 40 if (!this.IsDispose) 41 { 42 this.IsDispose = true; 43 try 44 { 45 try { this._Socket.Close(); } 46 catch { } 47 IDisposable disposable = this._Socket; 48 if (disposable != null) { disposable.Dispose(); } 49 this.Buffers = null; 50 GC.SuppressFinalize(this); 51 } 52 catch (Exception) { } 53 } 54 } 55 56 57 /// <summary> 58 /// 遞歸接收消息方法 59 /// </summary> 60 internal void ReceiveAsync() 61 { 62 try 63 { 64 if (!this.IsDispose && this._Socket.Connected) 65 { 66 this._Socket.BeginReceive(this.Buffers, 0, this.BufferSize, SocketFlags.None, out SenderError, this.aCallback, this); 67 CheckSocketError(ReceiveError); 68 } 69 } 70 catch (System.Net.Sockets.SocketException) { this.Close("鏈接已經(jīng)被關(guān)閉"); } 71 catch (System.ObjectDisposedException) { this.Close("鏈接已經(jīng)被關(guān)閉"); } 72 } 73 74 75 76 /// <summary> 77 /// 接收消息回調(diào)函數(shù) 78 /// </summary> 79 /// <param name="iar"></param> 80 private void ReceiveCallback(IAsyncResult iar) 81 { 82 if (!this.IsDispose) 83 { 84 try 85 { 86 //接受消息 87 ReceiveSize = _Socket.EndReceive(iar, out ReceiveError); 88 //檢查狀態(tài)碼 89 if (!CheckSocketError(ReceiveError) && SocketError.Success == ReceiveError) 90 { 91 //判斷接受的字節(jié)數(shù) 92 if (ReceiveSize > 0) 93 { 94 byte[] rbuff = new byte[ReceiveSize]; 95 Array.Copy(this.Buffers, rbuff, ReceiveSize); 96 this.Receive(rbuff); 97 //重置連續(xù)收到空字節(jié)數(shù) 98 ZeroCount = 0; 99 //繼續(xù)開始異步接受消息100 ReceiveAsync();101 }102 else103 {104 ZeroCount++;105 if (ZeroCount == 5) { this.Close("錯(cuò)誤鏈接"); }106 }107 }108 }109 catch (System.Net.Sockets.SocketException) { this.Close("鏈接已經(jīng)被關(guān)閉"); }110 catch (System.ObjectDisposedException) { this.Close("鏈接已經(jīng)被關(guān)閉"); }111 }112 }113 114 /// <summary>115 /// 錯(cuò)誤判斷116 /// </summary>117 /// <param name="socketError"></param>118 /// <returns></returns>119 bool CheckSocketError(SocketError socketError)120 {121 switch ((socketError))122 {123 case SocketError.SocketError:124 case SocketError.VersionNotSupported:125 case SocketError.TryAgain:126 case SocketError.ProtocolFamilyNotSupported:127 case SocketError.ConnectionAborted:128 case SocketError.ConnectionRefused:129 case SocketError.ConnectionReset:130 case SocketError.Disconnecting:131 case SocketError.HostDown:132 case SocketError.HostNotFound:133 case SocketError.HostUnreachable:134 case SocketError.NetworkDown:135 case SocketError.NetworkReset:136 case SocketError.NetworkUnreachable:137 case SocketError.NoData:138 case SocketError.OperationAborted:139 case SocketError.Shutdown:140 case SocketError.SystemNotReady:141 case SocketError.TooManyOpenSockets:142 this.Close(socketError.ToString());143 return true;144 }145 return false;146 }147 148 /// <summary>149 /// 發(fā)送消息方法150 /// </summary>151 internal int SendMsg(byte[] buffer)152 {153 int size = 0;154 try155 {156 if (!this.IsDispose)157 {158 size = this._Socket.Send(buffer, 0, buffer.Length, SocketFlags.None, out SenderError);159 CheckSocketError(SenderError);160 }161 }162 catch (System.ObjectDisposedException) { this.Close("鏈接已經(jīng)被關(guān)閉"); }163 catch (System.Net.Sockets.SocketException) { this.Close("鏈接已經(jīng)被關(guān)閉"); }164 buffer = null;165 return size;166 }167 }
上面我們事先了socket的異步接受消息,和同步發(fā)送消息已經(jīng)關(guān)閉釋放資源代碼
接受消息net底層提供的接受消息的方法有很多,為什么我們要選擇上面所寫的呢?那是為了兼容U3D,silverlight, wpf, wp, wf,等程序可執(zhí)行,不在重復(fù)做相同工作。
現(xiàn)在我們來創(chuàng)建一個(gè)實(shí)現(xiàn)類TSocketClient
1 public class TSocketClient : TSocketBase 2 { 3 /// <summary> 4 /// 是否是服務(wù)器端的資源 5 /// </summary> 6 bool isServer = false; 7 8 /// <summary> 9 /// 客戶端主動(dòng)請求服務(wù)器10 /// </summary>11 /// <param name="因?yàn)槭菧y試示例,所以我把服務(wù)器和客戶端實(shí)現(xiàn)類寫成了,只是用來不同的構(gòu)造函數(shù)來區(qū)分,是客戶端還是服務(wù)器的標(biāo)識
新聞熱點(diǎn)
疑難解答
圖片精選