程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C# Socket系列二 簡單的創建 socket 通信,

C# Socket系列二 簡單的創建 socket 通信,

編輯:C#入門知識

C# Socket系列二 簡單的創建 socket 通信,


看了系列一 我們開啟了對socket tcp的監聽狀態,那麼這一章我們來講解怎麼創建socket的通信代碼

我新建一個類 TSocketBase

  1 public abstract class TSocketBase
  2     {
  3         //封裝socket
  4         internal Socket _Socket;
  5         //回調
  6         private AsyncCallback aCallback;
  7         //接受數據的緩沖區
  8         private byte[] Buffers;
  9         //標識是否已經釋放
 10         private volatile bool IsDispose;
 11         //10K的緩沖區空間
 12         private int BufferSize = 10 * 1024;
 13         //收取消息狀態碼
 14         private SocketError ReceiveError;
 15         //發送消息的狀態碼
 16         private SocketError SenderError;
 17         //每一次接受到的字節數
 18         private int ReceiveSize = 0;
 19         //接受空消息次數
 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         /// 關閉並釋放資源
 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("鏈接已經被關閉"); }
 71             catch (System.ObjectDisposedException) { this.Close("鏈接已經被關閉"); }
 72         }
 73 
 74 
 75 
 76         /// <summary>
 77         /// 接收消息回調函數
 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                     //檢查狀態碼
 89                     if (!CheckSocketError(ReceiveError) && SocketError.Success == ReceiveError)
 90                     {
 91                         //判斷接受的字節數
 92                         if (ReceiveSize > 0)
 93                         {
 94                             byte[] rbuff = new byte[ReceiveSize];
 95                             Array.Copy(this.Buffers, rbuff, ReceiveSize);
 96                             this.Receive(rbuff);
 97                             //重置連續收到空字節數
 98                             ZeroCount = 0;
 99                             //繼續開始異步接受消息
100                             ReceiveAsync();
101                         }
102                         else
103                         {
104                             ZeroCount++;
105                             if (ZeroCount == 5) { this.Close("錯誤鏈接"); }
106                         }
107                     }
108                 }
109                 catch (System.Net.Sockets.SocketException) { this.Close("鏈接已經被關閉"); }
110                 catch (System.ObjectDisposedException) { this.Close("鏈接已經被關閉"); }
111             }
112         }
113 
114         /// <summary>
115         /// 錯誤判斷
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         /// 發送消息方法
150         /// </summary>
151         internal int SendMsg(byte[] buffer)
152         {
153             int size = 0;
154             try
155             {
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("鏈接已經被關閉"); }
163             catch (System.Net.Sockets.SocketException) { this.Close("鏈接已經被關閉"); }
164             buffer = null;
165             return size;
166         }
167     }

上面我們事先了socket的異步接受消息,和同步發送消息已經關閉釋放資源代碼

接受消息net底層提供的接受消息的方法有很多,為什麼我們要選擇上面所寫的呢?那是為了兼容U3D,silverlight, wpf, wp, wf,等程序可執行,不在重復做相同工作。

現在我們來創建一個實現類 TSocketClient

 1   public class TSocketClient : TSocketBase
 2     {
 3         /// <summary>
 4         /// 是否是服務器端的資源
 5         /// </summary>
 6         bool isServer = false;
 7 
 8         /// <summary>
 9         /// 客戶端主動請求服務器
10         /// </summary>
11         /// <param name="ip"></param>
12         /// <param name="port"></param>
13         public TSocketClient(string ip = "127.0.0.1", int port = 9527)
14         {
15             isServer = false;
16             this._Socket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
17             this._Socket.Connect(ip, port);
18             this.SetSocket();
19             this.ReceiveAsync();
20         }
21         /// <summary>
22         /// 這個是服務器收到有效鏈接初始化
23         /// </summary>
24         /// <param name="socket"></param>
25         public TSocketClient(Socket socket)
26         {
27             isServer = true;
28             this._Socket = socket;
29             this.SetSocket();
30             this.ReceiveAsync();
31         }
32 
33         /// <summary>
34         /// 收到消息後
35         /// </summary>
36         /// <param name="rbuff"></param>
37         public override void Receive(byte[] rbuff)
38         {
39             Console.WriteLine("Receive Msg:" + System.Text.UTF8Encoding.Default.GetString(rbuff));
40             if (isServer)
41             {
42                 this.SendMsg(System.Text.UTF8Encoding.Default.GetBytes("Holle Client!"));
43             }
44         }
45     }

因為是測試示例,所以我把服務器和客戶端實現類寫成了,只是用來不同的構造函數來區分,是客戶端還是服務器的標識

 

接下來我們測試一下代碼

 1   class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             TCPListener tcp = new TCPListener();
 6             TSocketClient client = new TSocketClient();
 7             client.SendMsg(System.Text.UTF8Encoding.Default.GetBytes("Holle Server!"));
 8             Console.ReadLine();
 9         }
10     }

 

運行結果看出,我們連接成功並且發送消息成功。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved