zoukankan      html  css  js  c++  java
  • 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     }

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

    跪求保留标示符
    /**
     * @author: Troy.Chen(失足程序员, 15388152619)
     * @version: 2021-07-20 10:55
     **/
    
    C#版本代码 vs2010及以上工具可以
    
    java 开发工具是netbeans 和 idea 版本,只有项目导入如果出现异常,请根据自己的工具调整
    
    
    提供免费仓储。
    最新的代码地址:↓↓↓
    https://gitee.com/wuxindao
    
    觉得我还可以,打赏一下吧,你的肯定是我努力的最大动力
        
    
  • 相关阅读:
    用C++实现从键盘输入两个数a和b,求两数中的最大值
    MongoDB学习笔记-1
    linux 配置ip地址
    linux 配置jdk 环境变量
    VMware Linux 共享文件夹 虚拟机无共享文件解决方法
    数据库动态参数
    js
    js分页
    mysql存储过程
    webconfig 中配置上传文件大小
  • 原文地址:https://www.cnblogs.com/shizuchengxuyuan/p/4344529.html
Copyright © 2011-2022 走看看