C#编写CS架构的基础实现

一、服务端实现

内部变量

包含两个套接字对象,一个网络终结点信息,读写buffer,信号控制对象,网络读写流。

        private Socket serverSocket = null;
        private Socket clientSocket = null;
        private IPEndPoint ie = null;
        private byte[] writeBuffer = new byte[1024];
        private byte[] readBuffer = new byte[1024];
        private Action<string> ccb = null;
        SocketAsyncEventArgs sae = new SocketAsyncEventArgs();
        SocketAsyncEventArgs revEvent = new SocketAsyncEventArgs();
        private NetworkStream sendStream;

构造函数

初始化异步回调事件对象,设置接收消息事件的接收Buffer,以及关联回调事件。

        public TcpServer()
        {
            sae = new SocketAsyncEventArgs();
            sae.Completed += AcceptEvent;
            revEvent = new SocketAsyncEventArgs();
            revEvent.SetBuffer(new byte[1024], 0, 1024);
            revEvent.Completed += RecvievEvent;


        }

接收事件回调

处理消息回调事件,将接收的字节流转换为字符串,通过外部注册好的回调事件将消息发送出去,接收完成后,异步请求下一次回调事件。

        private void RecvievEvent(object sender, SocketAsyncEventArgs e)
        {
            if (e.SocketError==SocketError.Success)
            {
                string stringdata = Encoding.Default.GetString(e.Buffer, 0, e.BytesTransferred);//把数组转换成16进制字符串
                ccb.Invoke("RecvievEvent" + stringdata);
                if (e.BytesTransferred == 0)
                {
                    ccb.Invoke("接收数据为0!");
                    clientSocket?.Close();
                    clientSocket = null;
                    return;
                }
                clientSocket.ReceiveAsync(revEvent);
            }
            else
            {

            }
           
        }

接收连接事件回调

传送连接信息,并记录相应的对应对象信息,设置接收Buffer,处理完成后,启用下一次接受事件。

        private void AcceptEvent(object sender, SocketAsyncEventArgs e)
        {
            if (e.SocketError == SocketError.Success)
            {
                ccb.Invoke("客户端连接:" + e.AcceptSocket.RemoteEndPoint.ToString());
                clientSocket = e.AcceptSocket;
                revEvent = new SocketAsyncEventArgs();
                revEvent.SetBuffer(new byte[1024], 0, 1024);
                revEvent.Completed += RecvievEvent;
                clientSocket.ReceiveAsync(revEvent);
                sae = new SocketAsyncEventArgs();
                sae.Completed += AcceptEvent;
                serverSocket.AcceptAsync(sae);
            }
            else
            {
                ccb.Invoke("客户端连接事件异常:" + e.SocketError);
            }
               
            
        }

服务器开启动作

根据传递的信息,设置服务器套接字的地址信息,并启动监听事件。

        public bool Start(string ip, int port, Action<string> cb)
        {
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            ie = new IPEndPoint(IPAddress.Parse(ip), port);
            serverSocket.Bind(ie);
            serverSocket.Listen(5);
            serverSocket.AcceptAsync(sae);
            sae = new SocketAsyncEventArgs();
            sae.Completed += AcceptEvent;
            ccb = cb;
            return true;
        }

发送消息动作

        public void SendMsg(string info)
        {
            clientSocket.Send(Encoding.Default.GetBytes(info));
        }

关闭动作

      internal void Close()
        {
            clientSocket?.Close();
            serverSocket.Close();
        }

调用示例

 TcpServer server = new TcpServer();//服务器
//开启服务器    最后一个函数为消息回调函数
server.Start(tbIP.Text, int.Parse(tbPort.Text), PrintInfo);
//发送消息
 server.SendMsg(tbMsg.Text);
//关闭服务器
 server.Close();

二、客户端实现

内部变量

包含一个套接字对象,一个网络终结点信息,读写buffer,异步事件处理对象,消息回调函数、重连定时器。

        private Socket client;
        private IPEndPoint iPEndPoint;
        private const int bufferSize = 128;
        private byte[] writeBuffer = new byte[bufferSize];
        private byte[] readBuffer = new byte[bufferSize];
        private SocketAsyncEventArgs sae = new SocketAsyncEventArgs();
        private Action<string> MsgCb = null;
        private bool IsOnline = false;
        private Timer timer;//重连定时器

构造函数

初始化异步接收事件对象,设置其接收Buffer,关联回调处理事件。

        public TcpCommClient()
        {
            sae = new SocketAsyncEventArgs();
            sae.SetBuffer(readBuffer, 0, bufferSize);
            sae.Completed += Sae_Completed;
        }

连接动作

根据调用方传递的地址信息,设置套接字地址信息,并启动异步接收事件。

        public bool Connect(string ip, int port, Action<string> rMsg)
        {
            try
            {
                client?.Close();
                client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                iPEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);
                client.Connect(iPEndPoint);
                MsgCb = rMsg;
                IsOnline = true;

                client.ReceiveAsync(sae);
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return false;
            }

        }

异常接收回调事件

将接收的字节流转接为字符串,并通过回调函数将消息传递出去,如果是接收为0,则开启重连定时器;如果正常接收则启用下下次异步接收。

        private void Sae_Completed(object sender, SocketAsyncEventArgs e)
        {
            try
            {
                string stringdata = Encoding.Default.GetString(e.Buffer, 0, e.BytesTransferred);//把数组转换为字符串
                stringdata = stringdata.Split('\r')[0];
                MsgCb.Invoke(stringdata);
                if (e.BytesTransferred == 0)
                {
                    IsOnline = false;
                    StartReconnection();
                    return;
                }
                if (client.Connected)
                {
                    client.ReceiveAsync(sae);
                }
                else
                {
                    IsOnline = false;
                    StartReconnection();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);

            }
        }

定时器执行重连动作

        public void StartReconnection()
        {
            timer = new Timer(Reconnection, null, 0, 1000);
        }

重连动作

尝试进行重新连接,连接后将相关对象重新创建,将设置好异步接收对象信息。如果失败,则销毁相关对象。

        private void Reconnection(object obj)
        {
            try
            {
                client?.Close();
                client?.Dispose();
                client = null;


                client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
               var asyRes= client.BeginConnect(iPEndPoint, null, null);
                asyRes.AsyncWaitHandle.WaitOne(10);
               // client.Connect(iPEndPoint);

                sae?.Dispose();
                sae = null;
                sae = new SocketAsyncEventArgs();
                sae.SetBuffer(new byte[bufferSize], 0, bufferSize);
                sae.Completed += Sae_Completed;

                client.ReceiveAsync(sae);
                IsOnline = true;
                timer.Dispose();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);

                client?.Dispose();
                client = null;
                sae?.Dispose();
                sae = null;
            }
        }

发送消息

        public bool SendMsg(string info)
        {
            try
            {
                if (!IsOnline)
                {
                    return false;
                }
                writeBuffer = Encoding.Default.GetBytes(info);

                int size = client.Send(writeBuffer);
                return size == writeBuffer.Length;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);

                return false;
            }
        }

关闭动作

        public bool Close()
        {
            try
            {
                timer?.Dispose();
                IsOnline = false;
                client.Shutdown(SocketShutdown.Both);
                client.Close();

                client.Dispose();
                client = null;
                sae.Dispose();
                sae = null;
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);

                return false;
            }
        }

调用示例

//创建对象
TcpCommClient client = new TcpCommClient();
//连接服务器  IP和端口来自UI元素  最后一个为消息回调函数
client.Connect(tbIP.Text, int.Parse(tbPort.Text), AddInfo);
//发送消息  消息来自UI元素
client.SendMsg(tbMsg.Text);
//关闭
client.Close();

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值