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     }

 

运行结果看出,我们连接成功并且发送消息成功。

 

posted on 2015-03-17 15:28  無心道(失足程序员)  阅读(965)  评论(0编辑  收藏  举报