zoukankan      html  css  js  c++  java
  • C# Socket系列二 简单的创建 socket 通信

    看了系列一 我们开启了对socket tcp的监听状态,那么这一章我们来讲解怎么创建socket的通信代码

    我新建一个类 TSocketBase

     
    public abstract class TSocketBase
        {
            //封装socket
            internal Socket _Socket;
            //回调
            private AsyncCallback aCallback;
            //接受数据的缓冲区
            private byte[] Buffers;
            //标识是否已经释放
            private volatile bool IsDispose;
            //10K的缓冲区空间
            private int BufferSize = 10*1024;
            //收取消息状态码
            private SocketError ReceiveError;
            //发送消息的状态码
            private SocketError SenderError;
            //每一次接受到的字节数
            private int ReceiveSize = 0;
            //接受空消息次数
            private byte ZeroCount = 0;
    
            public abstract void Receive(byte[] rbuff);
    
            public void SetSocket()
            {
                this.aCallback = new AsyncCallback(this.ReceiveCallback);
                this.IsDispose = false;
                this._Socket.ReceiveBufferSize = this.BufferSize;
                this._Socket.SendBufferSize = this.BufferSize;
                this.Buffers = new byte[this.BufferSize];
            }
    
    
            /// <summary>
            /// 关闭并释放资源
            /// </summary>
            /// <param name="msg"></param>
            public void Close(string msg)
            {
                if (!this.IsDispose)
                {
                    this.IsDispose = true;
                    try
                    {
                        try
                        {
                            this._Socket.Close();
                        }
                        catch
                        {
                        }
                        IDisposable disposable = this._Socket;
                        if (disposable != null)
                        {
                            disposable.Dispose();
                        }
                        this.Buffers = null;
                        GC.SuppressFinalize(this);
                    }
                    catch (Exception)
                    {
                    }
                }
            }
    
    
            /// <summary>
            /// 递归接收消息方法
            /// </summary>
            internal void ReceiveAsync()
            {
                try
                {
                    if (!this.IsDispose && this._Socket.Connected)
                    {
                        this._Socket.BeginReceive(this.Buffers, 0, this.BufferSize, SocketFlags.None, out SenderError,
                            this.aCallback, this);
                        CheckSocketError(ReceiveError);
                    }
                }
                catch (System.Net.Sockets.SocketException)
                {
                    this.Close("链接已经被关闭");
                }
                catch (System.ObjectDisposedException)
                {
                    this.Close("链接已经被关闭");
                }
            }
    
    
    
            /// <summary>
            /// 接收消息回调函数
            /// </summary>
            /// <param name="iar"></param>
            private void ReceiveCallback(IAsyncResult iar)
            {
                if (!this.IsDispose)
                {
                    try
                    {
                        //接受消息
                        ReceiveSize = _Socket.EndReceive(iar, out ReceiveError);
                        //检查状态码
                        if (!CheckSocketError(ReceiveError) && SocketError.Success == ReceiveError)
                        {
                            //判断接受的字节数
                            if (ReceiveSize > 0)
                            {
                                byte[] rbuff = new byte[ReceiveSize];
                                Array.Copy(this.Buffers, rbuff, ReceiveSize);
                                this.Receive(rbuff);
                                //重置连续收到空字节数
                                ZeroCount = 0;
                                //继续开始异步接受消息
                                ReceiveAsync();
                            }
                            else
                            {
                                ZeroCount++;
                                if (ZeroCount == 5)
                                {
                                    this.Close("错误链接");
                                }
                            }
                        }
                    }
                    catch (System.Net.Sockets.SocketException)
                    {
                        this.Close("链接已经被关闭");
                    }
                    catch (System.ObjectDisposedException)
                    {
                        this.Close("链接已经被关闭");
                    }
                }
            }
    
            /// <summary>
            /// 错误判断
            /// </summary>
            /// <param name="socketError"></param>
            /// <returns></returns>
            private bool CheckSocketError(SocketError socketError)
            {
                switch ((socketError))
                {
                    case SocketError.SocketError:
                    case SocketError.VersionNotSupported:
                    case SocketError.TryAgain:
                    case SocketError.ProtocolFamilyNotSupported:
                    case SocketError.ConnectionAborted:
                    case SocketError.ConnectionRefused:
                    case SocketError.ConnectionReset:
                    case SocketError.Disconnecting:
                    case SocketError.HostDown:
                    case SocketError.HostNotFound:
                    case SocketError.HostUnreachable:
                    case SocketError.NetworkDown:
                    case SocketError.NetworkReset:
                    case SocketError.NetworkUnreachable:
                    case SocketError.NoData:
                    case SocketError.OperationAborted:
                    case SocketError.Shutdown:
                    case SocketError.SystemNotReady:
                    case SocketError.TooManyOpenSockets:
                        this.Close(socketError.ToString());
                        return true;
                }
                return false;
            }
    
            /// <summary>
            /// 发送消息方法
            /// </summary>
            internal int SendMsg(byte[] buffer)
            {
                int size = 0;
                try
                {
                    if (!this.IsDispose)
                    {
                        size = this._Socket.Send(buffer, 0, buffer.Length, SocketFlags.None, out SenderError);
                        CheckSocketError(SenderError);
                    }
                }
                catch (System.ObjectDisposedException)
                {
                    this.Close("链接已经被关闭");
                }
                catch (System.Net.Sockets.SocketException)
                {
                    this.Close("链接已经被关闭");
                }
                buffer = null;
                return size;
            }
        }
    

      

    上面我们事先了socket的异步接受消息,和同步发送消息已经关闭释放资源代码

    接受消息net底层提供的接受消息的方法有很多,为什么我们要选择上面所写的呢?那是为了兼容U3D,silverlight, wpf, wp, wf,等程序可执行,不在重复做相同工作。

    现在我们来创建一个实现类 TSocketClient

    public class TSocketClient : TSocketBase
        {
            /// <summary>
            /// 是否是服务器端的资源
            /// </summary>
            private bool isServer = false;
    
            /// <summary>
            /// 客户端主动请求服务器
            /// </summary>
            /// <param name="ip"></param>
            /// <param name="port"></param>
            public TSocketClient(string ip = "127.0.0.1", int port = 9527)
            {
                isServer = false;
                this._Socket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                this._Socket.Connect(ip, port);
                this.SetSocket();
                this.ReceiveAsync();
            }
    
            /// <summary>
            /// 这个是服务器收到有效链接初始化
            /// </summary>
            /// <param name="socket"></param>
            public TSocketClient(Socket socket)
            {
                isServer = true;
                this._Socket = socket;
                this.SetSocket();
                this.ReceiveAsync();
            }
    
            /// <summary>
            /// 收到消息后
            /// </summary>
            /// <param name="rbuff"></param>
            public override void Receive(byte[] rbuff)
            {
                Console.WriteLine("Receive Msg:" + System.Text.UTF8Encoding.Default.GetString(rbuff));
                if (isServer)
                {
                    this.SendMsg(System.Text.UTF8Encoding.Default.GetBytes("Holle Client!"));
                }
            }
        }
    

      

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

    接下来我们测试一下代码

    复制代码
     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     }
    复制代码

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

  • 相关阅读:
    WordCount项目基本功能
    让自己的头脑极度开放
    Docker安装Mysql5.7
    MySQL中的函数索引(Generated Column)及一次SQL优化
    关于老系统的重构和优化选择
    JIRA笔记(一):安装部署JIRA
    Jenkins 配置GitLab插件和Git插件
    Loading descriptor for XXX.'has encountered a problem' A internal error occured during:"Loading ....."
    Newton插值的C++实现
    Lagrange插值C++程序
  • 原文地址:https://www.cnblogs.com/soundcode/p/7238616.html
Copyright © 2011-2022 走看看