TCP通信之异步实现

首先本内容是参考于别人的一篇文章,由于时间久远没找到原作者。今天写本篇文章用于技术记录,便于日后查看。

 

服务端:

public class TCPServer
    {
        static byte[] buffer = new byte[1024];
        private static int count = 0;
        public static Socket socket = null;
        public static Socket socketClient = null;

        /// <summary>
        /// 客服端
        /// </summary>
        public static Socket client = null;

        /// <summary>
        /// 启动监听
        /// </summary>
        public static void Start(string ip, string port)
        {
            try
            {
                #region 启动程序
                //①创建一个新的Socket,这里我们使用最常用的基于TCP的Stream Socket(流式套接字)
                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //string ip = OperIni.ReadIni("BJIP", "key", "", Program.MainForm.iniFilePath);
                //string port = OperIni.ReadIni("BJPORT", "key", "", Program.MainForm.iniFilePath);
                //②将该socket绑定到主机上面的某个端口
                //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.bind.aspx
                socket.Bind(new IPEndPoint(IPAddress.Parse(ip), Int32.Parse(port)));

                //③启动监听,并且设置一个最大的队列长度
                //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.listen(v=VS.100).aspx
                socket.Listen(10000);

                //④开始接受客户端连接请求
                //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.beginaccept.aspx
                socket.BeginAccept(new AsyncCallback(ClientAccepted), socket);
                #endregion
            }
            catch (Exception err)
            {
               // MessageBox.Show("服务器监听打开失败:" + err.Message, "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #region 客户端连接成功
        /// <summary>
        /// 客户端连接成功
        /// </summary>
        /// <param name="ar"></param>
        public static void ClientAccepted(IAsyncResult ar)
        {
            #region
            //设置计数器
            count++;
           // var socket = ar.AsyncState as Socket;



            //这就是客户端的Socket实例,我们后续可以将其保存起来
            client = socket.EndAccept(ar);
            //客户端IP地址和端口信息
            IPEndPoint clientipe = (IPEndPoint)client.RemoteEndPoint;

            //WriteLine(clientipe + " is connected,total connects " + count, ConsoleColor.Yellow);

            //接收客户端的消息(这个和在客户端实现的方式是一样的)异步
            client.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), client);
            //准备接受下一个客户端请求(异步)
            socket.BeginAccept(new AsyncCallback(ClientAccepted), socket);
            #endregion
        }
        #endregion

        #region 接收和发送客户端的信息

        /// <summary>
        /// 接收某一个客户端的消息
        /// </summary>
        /// <param name="ar"></param>
        public static void ReceiveMessage(IAsyncResult ar)
        {
            int length = 0;
            string message = ""; //收到到的消息
            socketClient = ar.AsyncState as Socket;
            //客户端IP地址和端口信息
            IPEndPoint clientipe = (IPEndPoint)socketClient.RemoteEndPoint;
            try
            {
                #region
                //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.endreceive.aspx
                length = socketClient.EndReceive(ar);
                if (length == 0)
                {
                    throw new Exception("客户端断开");
                }

                //读取出来消息内容
                //ASCIIEncoding ASC = new ASCIIEncoding();
                //message = ASC.GetString(buffer, 0, length);
                message = Encoding.Default.GetString(buffer);
                //输出接收信息
                WriteLine(clientipe + "" + message, ConsoleColor.White);



                //接收下一个消息(因为这是一个递归的调用,所以这样就可以一直接收消息)异步
                socketClient.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socketClient);
                #endregion
            }
            catch (Exception ex)
            {
                //设置计数器
                count--;
                //断开连接
                //WriteLine(clientipe + " is disconnected,total connects " + (count), ConsoleColor.Red);
            }
        }

        /// <summary>
        /// 发送客户端消息
        /// </summary>        
        public static void Send(string send)
        {
            try
            {

                byte[] reply = Encoding.GetEncoding("GB2312").GetBytes(send);
                client.Send(reply);

            }
            catch (Exception err)
            {
               // MessageBox.Show("与主控通信失败!" + err.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }

        }
        #endregion

        #region 扩展方法
        public static void WriteLine(string str, ConsoleColor color)
        {
            Console.ForegroundColor = color;
            Console.WriteLine("[{0}] {1}", DateTime.Now.ToString("MM-dd HH:mm:ss"), str);
        }

        /// <summary>
        /// 校验和
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static byte SumMake(byte[] msg)
        {
            byte b = 0;
            for (int i = 1; i < msg.Length - 2; i++)
            {
                b += msg[i];
            }
            return b;

        }
        #endregion
    }

 

客户端:

 class TCPClient
    {
        private Socket clientSocket;
        private byte[] receiveBuff;

        public TCPClient()
        {
            receiveBuff = new byte[1024];
        }

        /// <summary>
        /// 打开连接
        /// </summary>
        /// <returns></returns>
        public bool connect(string ip, int port)
        {
            try
            {
                if (clientSocket == null || clientSocket.Connected == false)
                {
                    clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//初始化套接字
                }

                IPEndPoint remotepoint = new IPEndPoint(IPAddress.Parse(ip), port);//根据ip地址和端口号创建远程终结点
                EndPoint end = (EndPoint)remotepoint;
                clientSocket.BeginConnect(end, new AsyncCallback(ConnectedCallback), clientSocket); //调用回调函数

                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine("设备连接失败:" + ex.Message);
                return false;
            }
        }

        private void ConnectedCallback(IAsyncResult ar)
        {
            try
            {
                Socket client = (Socket)ar.AsyncState;
                client.EndConnect(ar);
                clientSocket.BeginReceive(receiveBuff, 0, receiveBuff.Length, 0, new AsyncCallback(ReceiveCallback), clientSocket);
                Console.WriteLine("设备连接成功:" + client.RemoteEndPoint);
            }
            catch (Exception e)
            {
                Console.WriteLine("设备连接失败:" + e.Message);
            }
        }

        private void ReceiveCallback(IAsyncResult ar)
        {
            try
            {
                String content = String.Empty;

                // Retrieve the state object and the handler socket
                // from the asynchronous state object.

                Socket handler = (Socket)ar.AsyncState;//获取句柄

                // Read data from the client socket. 
                int bytesRead = handler.EndReceive(ar);
                IPEndPoint remotepoint = (IPEndPoint)handler.RemoteEndPoint;//获取远程的端口

                if (bytesRead > 0)
                {
                    //处理收到的信息
                    DealReceive(receiveBuff, bytesRead);

                    //处理完之后清空receive_buff
                    clearReceiveBuff();

                    clientSocket.BeginReceive(receiveBuff, 0, receiveBuff.Length, 0, new AsyncCallback(ReceiveCallback), handler);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                clearReceiveBuff();
            }
        }

        private void SendCallback(IAsyncResult ar) //发送的回调函数
        {
            Socket client = (Socket)ar.AsyncState;
            int bytesSend = client.EndSend(ar); //完成发送
        }

        private void DealReceive(Byte[] receiveByte, int len)
        {
            byte[] temp = new byte[len];
            Array.Copy(receiveByte, 0, temp, 0, len);

            //string strReceive = StringConvert.byteToHexStr(temp);
            string strReceive = Encoding.Default.GetString(temp);

            Console.WriteLine(strReceive);
        }

        private void clearReceiveBuff()
        {
            Array.Clear(receiveBuff, 0, 1024);
        }

        public void sendToServer(byte[] byteData)
        {
            try
            {
                if (clientSocket != null && clientSocket.Connected)
                {
                    clientSocket.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), clientSocket);
                }
            }
            catch (SocketException ex)
            {
                Console.WriteLine("TCP发送失败:" + ex.Message);
            }
        }

    }

 

posted @ 2021-12-15 20:47  追风少年2021  阅读(463)  评论(0)    收藏  举报