C# Socket系列二 简单的创建 socket 通信

8/3/2015来源:C#应用人气:2113

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                         else103                         {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             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("链接已经被关闭"); }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     }

因为是测试示例,所以我把服务器和客户端实现类写成了,只是用来不同的构造函数来区分,是客户端还是服务器的标识