C#实现异步阻塞TCP(Send,Receive,Accept,Connect)

1.类

(1)服务器端操作类

    public class TcpServiceSocket
    {
        //接收数据事件
        public Action<Socket, string> recvMessageEvent = null;
        //发送结果事件
        public Action<int> sendResultEvent = null;
        //允许连接到tcp服务器的tcp客户端数量
        private int numConnections = 0;
        //连接socket
        private Socket listenSocket = null;
        //tcp服务器ip
        private string host = "";
        //tcp服务器端口
        private int port = 0;
        //控制tcp客户端连接数量的信号量
        private Semaphore maxNumberAcceptedClients = null;
        private int bufferSize = 1024;
        private List<Socket> clientSockets = null;

        public TcpServiceSocket(string host, int port, int numConnections)
        {
            if (string.IsNullOrEmpty(host))
                throw new ArgumentNullException("host cannot be null");
            if (port < 1 || port > 65535)
                throw new ArgumentOutOfRangeException("port is out of range");
            if (numConnections <= 0 || numConnections > int.MaxValue)
                throw new ArgumentOutOfRangeException("_numConnections is out of range");

            this.host = host;
            this.port = port;
            this.numConnections = numConnections;
            clientSockets = new List<Socket>();
            maxNumberAcceptedClients = new Semaphore(numConnections, numConnections);
        }

        public void Start()
        {
            try
            {
                listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                listenSocket.Bind(new IPEndPoint(IPAddress.Parse(host), port));
                listenSocket.Listen(numConnections);
                AcceptAsync();
            }
            catch (Exception)
            {
            }
        }

        private async void AcceptAsync()
        {
            await Task.Run(new Action(() =>
            {
                while (true)
                {
                    maxNumberAcceptedClients.WaitOne();

                    try
                    {
                        Socket acceptSocket = listenSocket.Accept();
                        if (acceptSocket == null)
                            continue;

                        clientSockets.Add(acceptSocket);
                        RecvAsync(acceptSocket);
                    }
                    catch (Exception)
                    {
                        maxNumberAcceptedClients.Release();
                    }
                }
            }));
        }

        private async void RecvAsync(Socket acceptSocket)
        {
            await Task.Run(new Action(() =>
            {
                int len = 0;
                byte[] buffer = new byte[bufferSize];

                try
                {
                    while ((len = acceptSocket.Receive(buffer, bufferSize, SocketFlags.None)) > 0)
                    {
                        if (recvMessageEvent != null)
                            recvMessageEvent(acceptSocket, Encoding.UTF8.GetString(buffer, 0, len));
                    }
                }
                catch (Exception)
                {
                    CloseClientSocket(acceptSocket);
                }
            }));
        }

        public async void SendAsync(Socket acceptSocket, string message)
        {
            await Task.Run(new Action(() =>
            {
                int len = 0;
                byte[] buffer = Encoding.UTF8.GetBytes(message);
                try
                {
                    if ((len = acceptSocket.Send(buffer, buffer.Length, SocketFlags.None)) > 0)
                    {
                        if (sendResultEvent != null)
                            sendResultEvent(len);
                    }
                }
                catch (Exception)
                {
                    CloseClientSocket(acceptSocket);
                }
            }));
        }

        public async void SendMessageToAllClientsAsync(string message)
        {
            await Task.Run(new Action(() =>
            {
                foreach (var socket in clientSockets)
                {
                    SendAsync(socket, message);
                }
            }));
        }

        private void CloseClientSocket(Socket acceptSocket)
        {
            try
            {
                acceptSocket.Shutdown(SocketShutdown.Both);
            }
            catch { }
            try
            {
                acceptSocket.Close();
            }
            catch { }

            maxNumberAcceptedClients.Release();
        }

        public void CloseAllClientSocket(Socket acceptSocket)
        {
            try
            {
                foreach (var socket in clientSockets)
                {
                    socket.Shutdown(SocketShutdown.Both);
                }
            }
            catch { }
            try
            {
                foreach (var socket in clientSockets)
                {
                    socket.Close();
                }
            }
            catch { }

            try
            {
                listenSocket.Shutdown(SocketShutdown.Both);
            }
            catch { }
            try
            {
                listenSocket.Close();
            }
            catch { }

            try
            {
                maxNumberAcceptedClients.Release(clientSockets.Count);
                clientSockets.Clear();
            }
            catch { }
        }
    }

  

(2)客户端操作类

    public class TcpClientSocket
    {
        //接收数据事件
        public Action<string> recvMessageEvent = null;
        //发送结果事件
        public Action<int> sendResultEvent = null;
        //连接socket
        private Socket connectSocket = null;
        //tcp服务器ip
        private string host = "";
        //tcp服务器端口
        private int port = 0;
        private int bufferSize = 1024;

        public TcpClientSocket(string host, int port)
        {
            if (string.IsNullOrEmpty(host))
                throw new ArgumentNullException("host cannot be null");
            if (port < 1 || port > 65535)
                throw new ArgumentOutOfRangeException("port is out of range");

            this.host = host;
            this.port = port;
        }

        public void Start()
        {
            try
            {
                connectSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                connectSocket.Connect(host, port);
                RecvAsync();
            }
            catch (Exception)
            {
            }
        }

        private async void RecvAsync()
        {
            await Task.Run(new Action(() =>
            {
                int len = 0;
                byte[] buffer = new byte[bufferSize];
                try
                {
                    while ((len = connectSocket.Receive(buffer, bufferSize, SocketFlags.None)) > 0)
                    {
                        if (recvMessageEvent != null)
                            recvMessageEvent(Encoding.UTF8.GetString(buffer, 0, len));
                    }
                }
                catch (Exception)
                {
                    Restart();
                }
            }));
        }

        public async void SendAsync(string message)
        {
            await Task.Run(new Action(() =>
            {
                int len = 0;
                byte[] buffer = Encoding.UTF8.GetBytes(message);
                try
                {
                    if ((len = connectSocket.Send(buffer, buffer.Length, SocketFlags.None)) > 0)
                    {
                        if (sendResultEvent != null)
                            sendResultEvent(len);
                    }
                }
                catch (Exception)
                {
                    Restart();
                }
            }));
        }

        public void CloseClientSocket()
        {
            try
            {
                connectSocket.Shutdown(SocketShutdown.Both);
            }
            catch { }
            try
            {
                connectSocket.Close();
            }
            catch { }
        }

        public void Restart()
        {
            CloseClientSocket();
            Start();
        }

    }

  

2.使用

(1)服务器:

    public partial class Form1 : Form
    {
        TcpServiceSocket tcpServiceSocket = null;
        private readonly string ip = "192.168.172.142";
        private readonly int port = 8090;

        public Form1()
        {
            InitializeComponent();
            tcpServiceSocket = new TcpServiceSocket(ip, port, 10);
            tcpServiceSocket.recvMessageEvent += new Action<Socket, string>(Recv);
        }

        private void Recv(Socket socket, string message)
        {
            this.BeginInvoke(new Action(() =>
            {
                tbRecv.Text += message + "\r\n";
            }));
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            tcpServiceSocket.Start();
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            string message = tbSend.Text.Trim();
            if (string.IsNullOrEmpty(message))
                return;

            tcpServiceSocket.SendMessageToAllClientsAsync(message);
            tbSend.Text = "";
        }
    }

  

(2)客户端

    public partial class Form1 : Form
    {
        private TcpClientSocket tcpClientSocket = null;
        private readonly string ip = "192.168.172.142";
        private readonly int port = 8090;

        public Form1()
        {
            InitializeComponent();
            tcpClientSocket = new TcpClientSocket(ip, port);
            tcpClientSocket.recvMessageEvent += new Action<string>(Recv);
        }

        private void Recv(string message)
        {
            this.BeginInvoke(new Action(() =>
            {
                tbRecv.Text += message + "\r\n";
            }));
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            tcpClientSocket.Start();
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            string message = tbSend.Text.Trim();
            if (string.IsNullOrEmpty(message))
                return;

            tcpClientSocket.SendAsync(message);
            tbSend.Text = "";
        }
    }

  

 

posted @ 2019-07-11 16:32  翻白眼的哈士奇  阅读(2531)  评论(0编辑  收藏  举报