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!"));
            }
        }
    }

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

    接下来我们测试一下代码

    class Program
    {
        static void Main(string[] args)
        {
            TCPListener tcp = new TCPListener();
            TSocketClient client = new TSocketClient();
            client.SendMsg(System.Text.UTF8Encoding.Default.GetBytes("Holle Server!"));
            Console.ReadLine();
        }
    }

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

  • 相关阅读:
    牛客小白月赛3 I 排名【结构体排序/较复杂/细节】
    牛客小白月赛3 F 异或【区间交集】
    牛客小白月赛3 B 躲藏【动态规划/字符串出现cwbc子序列多少次】
    陕西师范大学第七届程序设计竞赛网络同步赛 I 排队排队排队【数组任一位可以移动到队头,最少移动几次增序/数组指针操作】
    陕西师范大学第七届程序设计竞赛网络同步赛 J 黑猫的小老弟【数论/法拉数列/欧拉函数】
    陕西师范大学第七届程序设计竞赛网络同步赛D ZQ的睡前故事【约瑟夫环1-N数到第k个出队,输出出队顺序/ STL模拟】
    陕西师范大学第七届程序设计竞赛网络同步赛 C iko和她的糖【贪心/ STL-优先队列/ 从1-N每个点有能量补充,每段有消耗,选三个点剩下最多能量】
    陕西师范大学第七届程序设计竞赛网络同步赛 F WWX的礼物【数学/k进制下x^n的位数/log】
    NYOJ 71 乘船问题【贪心】
    hdu 5273 Dylans loves sequence
  • 原文地址:https://www.cnblogs.com/zhaoshujie/p/11049816.html
Copyright © 2011-2022 走看看