C# TCP客户端简单异步通讯实例(源码)

对应上篇文章的服务端,和之前一个tcp异步通讯方法大致一致,不过这个相当于是单独的客户端通讯。

所实现的效果,左上添加客户端,添加后的客户端会追加到下拉框列表中,切换不同的下拉框对应不同的服务端通讯

实现客户端tcp通讯 

#region 变量及属性

        /// <summary>
        /// 确保id唯一
        /// </summary>
        int comid = 0;
        /// <summary>
        /// 客户端连接实例
        /// </summary>
        private Dictionary<int, ClientMess> comlistDic=new Dictionary<int, ClientMess>();
        /// <summary>
        /// 绑定下拉框
        /// </summary>
        private Dictionary<int,string> comListstringDic=new Dictionary<int,string>();
        //当前下拉框选择的类
        ClientMess NowClientClass=new ClientMess();

        /// <summary>
        /// 客户端连接信息类
        /// </summary>
        public class ClientMess
        {
            public int CComid=0;
            public string CIp="";
            public string CPort="";
            public Socket CSocket=null;
            public bool CIfConn=false;
            public string CRecvStr="";
        }
        public class StateObject
        {
            // 当前客户端的Socket
            public Socket workSocket = null;
            // 可接收的最大字节数
            public const int BufferSize = 1024 * 1024;
            // 接收的数据存储
            public byte[] buffer = new byte[BufferSize];
        }

        //内存缓存区
        public static Socket client;
        public static IPEndPoint serverPoint = null;
        #endregion

 

 

 /// <summary>
        /// 连接服务端
        /// </summary>
        /// <param name="ip">Ip</param>
        /// <param name="port">端口</param>
        public bool ConnectServercer(string ip, string port)
        {
            IPAddress IP = IPAddress.Parse(ip.Trim());
            serverPoint = new IPEndPoint(IP, Convert.ToInt32(port));
            try
            {
                client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                client.BeginConnect(serverPoint, new AsyncCallback(ConnectCallback), client);
                Thread.Sleep(500);//异步等500毫秒返回连接结果
                return client.Connected;
            }
            catch (Exception ex)
            {
                MessageBox.Show("异常-客户端开启连接", client.LocalEndPoint + "异常:【" + ex.Message + "】");
                return false;
            }
        }

        private void ConnectCallback(IAsyncResult ar) //连接客户端异步回调
        {
            client = (Socket)ar.AsyncState;
            try
            {
                if (client != null && client.Connected)
                {
                    client.EndConnect(ar);
                    Receive(client);
                    NowClientClass.CSocket = client;
                    NowClientClass.CRecvStr+= (DateTime.Now + client.LocalEndPoint.ToString() + " 成功连接服务端:" + client.RemoteEndPoint.ToString() + "\r\n");
                    NowClientClass.CIfConn = true;
                    this.Invoke(new Action(() =>//线程间操作无效: 从不是创建控件的线程访问它,使用委托
                    {
                        button6.Enabled = false;//连接按钮
                        button7.Enabled = true;//断开按钮
                        textBox7.Text = NowClientClass.CRecvStr;//接收区
                    label6.Text = client.LocalEndPoint.ToString();//本地ip端口就
                    }));
                }
                else
                {
                    MessageBox.Show("服务端未开启");
                    client.Close();
                }
            }
            catch (Exception ex)
            {
               MessageBox.Show("异常-客户端连接回调" + client.LocalEndPoint, "异常连接" + serverPoint + "【" + ex.Message + "】");
            }
        }

        //接收消息
        private void Receive(Socket client)
        {
            StateObject state = new StateObject();
            state.workSocket = client;
            client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
        }
        //接收消息异步回调
        private void ReceiveCallback(IAsyncResult ar)
        {
            StateObject state = (StateObject)ar.AsyncState;
            client = state.workSocket;
            EndPoint endpoint = null;
            try
            {
                if (client != null && client.Connected)
                {
                    endpoint = client.LocalEndPoint;
                    int bytesRead = client.EndReceive(ar);
                    if (bytesRead > 0)//读取到服务端发送过来的字节长度
                    {
                        byte[] ActConn = new byte[bytesRead];
                        Buffer.BlockCopy(state.buffer, 0, ActConn, 0, bytesRead);//将接收到的byte复制接收到的字节长度到新的byte集合中
                        this.Invoke(new Action(() =>
                            {
                              if (radioButton7.Checked)//hex接收
                                {
                                    NowClientClass.CRecvStr +=(DateTime.Now + " 【接收】" + client.RemoteEndPoint + "发送的数据 :"+ BitConverter.ToString(ActConn, 0, ActConn.Length).Replace("-", "") + "\r\n");
                                }
                                else//ascll
                                {
                                    NowClientClass.CRecvStr += (DateTime.Now + " 【接收】" + client.RemoteEndPoint + "发送的数据 :" + Encoding.Default.GetString(ActConn) + "\r\n");
                                }
                                textBox7.Text = NowClientClass.CRecvStr;
                            }));
                        client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);//继续接收数据
                    }
                    else
                    {
                        if (client != null && client.Connected)
                        {
                            client.Close();//关闭连接
                        }
                        this.Invoke(new Action(() =>//异步中操作控件报错:线程间操作无效: 从不是创建控件的线程访问它  使用委托
                        {

                            button6.Enabled = true;//连接按钮
                            button7.Enabled = false;//断开按钮
                            NowClientClass.CIfConn = false;//当前客户端连接状态
                            NowClientClass.CRecvStr +=( DateTime.Now + " 【接收】服务端发送的空字符串:服务端断开连接" + "\r\n");
                            textBox7.Text = NowClientClass.CRecvStr;
                        }));
                    }
                }
                else
                {
                    client.Close(); 
                    this.Invoke(new Action(() =>
                    {

                        button6.Enabled = true;
                        button7.Enabled = false;
                        NowClientClass.CIfConn = false;
                        string aa = NowClientClass.CRecvStr + DateTime.Now + " 【接收】服务端发送的信息:服务端断开连接" + "\r\n";
                        NowClientClass.CRecvStr = aa;
                        textBox7.Text = aa;
                    }));
                    //服务端断开连接
                }
            }
            catch (Exception ex)
            {
                if (client != null && client.Connected)
                {
                    client.Close();
                }
                if (endpoint != null)
                {
                   MessageBox.Show("异常-客户端接收消息回调" + endpoint, serverPoint + "异常【" + ex.Message + "】");
                }
                else
                {
                   MessageBox.Show("异常-客户端接收消息回调", serverPoint + "异常【" + ex.Message + "】");
                }
            }
        }

        /// <summary>
        /// 向服务端发送消息
        /// </summary>
        /// <param name="sendMsg"></param>
        public static void Send(Socket socket, byte[] sendmessage)
        {
            try
            {
                if (socket != null && socket.Connected)
                {
                    socket.BeginSend(sendmessage, 0, sendmessage.Length, 0, new AsyncCallback(SendCallback), socket);
                }
            }
            catch (Exception ex)
            {
               MessageBox.Show("异常-客户端发送消息异常" + socket.LocalEndPoint, serverPoint + "【" + ex.Message + "】");
            }
        }
        //发送消息异步回调
        private static void SendCallback(IAsyncResult ar)
        {
            try
            {
                // 从异步状态中检索socket
                Socket client = (Socket)ar.AsyncState;
                // 完成将数据发送到服务端
                int bytesSent = client.EndSend(ar);
                // 表示所有自己均已发送
                //sendDone.Set();
            }
            catch (Exception ex)
            {
                MessageBox.Show("异常-客户端发送消息回调异常" + client.LocalEndPoint, serverPoint + "【" + ex.Message + "】");
            }
        }
        ClientMess clm;
        private void button10_Click(object sender, EventArgs e)//添加客户端
        {
            if(textBox4.Text.Length>0&& textBox5.Text.Length > 0)
            {
                bool m = Regex.IsMatch(textBox4.Text, "^((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})(\\.((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})){3}$");   // 匹配正则表达式
                if (m == false)
                {
                    MessageBox.Show("IP输入格式不正确!请修改");
                    return;
                }
                clm =new ClientMess();
                clm.CIp=textBox4.Text;
                clm.CPort=textBox5.Text;
                comlistDic.Add(comid, clm);
                comListstringDic.Add(comid, textBox4.Text + ":" + textBox5.Text);
                comboBox2.ValueMember = "key";
                comboBox2.DisplayMember = "value";
                comboBox2.DataSource = new BindingSource() { DataSource = comListstringDic };
                comid++;
            }
        }

        private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)//根据不同客户端切换接收区内容
        {
            if (comboBox2.SelectedItem==null)
            {
                return;
            }
          var aa = ((KeyValuePair<int, string>)comboBox2.SelectedItem).Key;//结构体,定义可设置或检索的键/值对。也就是说我们可以通过 它记录一个键/值对这样的值。将选择的值转换以方便获取键值
            if (comlistDic[aa].CIfConn)
            {
                button6.Enabled = false;
                button7.Enabled = true;
            }
            else
            {
                button6.Enabled = true;
                button7.Enabled = false;
            }
            NowClientClass = comlistDic[aa];
            if (NowClientClass.CSocket != null&&NowClientClass.CSocket.Connected)
            {
                label6.Text = NowClientClass.CSocket.LocalEndPoint.ToString();
            }
            else
            {
                label6.Text = "0";
            }
            textBox7.Text = NowClientClass.CRecvStr;
        }

        private void button2_Click(object sender, EventArgs e)//清空接收区
        {
            textBox7.Text = string.Empty;
           NowClientClass.CRecvStr = "";
        }

        private void button6_Click(object sender, EventArgs e)//连接
        {
            int index = comboBox2.Text.IndexOf(":");
            if(index != -1)
            {
            ConnectServercer(comboBox2.Text.Substring(0, index), comboBox2.Text.Substring(index+1));
            }
        }

        private void button7_Click(object sender, EventArgs e)//断开
        {   if(NowClientClass.CIfConn)
            {
                NowClientClass.CSocket.Shutdown(SocketShutdown.Both);//停止接收发送数据
                NowClientClass.CSocket.Close();//关闭连接
            }
            button6.Enabled = true;
            button7.Enabled = false;
            NowClientClass.CIfConn = false;
        }

        private void button11_Click(object sender, EventArgs e)//删除
        {
            if (comboBox2.Text.Length > 0)
            {
                if (NowClientClass.CIfConn)
                {
                    NowClientClass.CSocket.Shutdown(SocketShutdown.Both);//停止接收发送数据
                    NowClientClass.CSocket.Close();//关闭连接
                }
                NowClientClass.CIfConn = false;
                NowClientClass.CRecvStr = "";
                textBox7.Text = "";
                var aa = ((KeyValuePair<int, string>)comboBox2.SelectedItem).Key;
                comlistDic.Remove(aa);
                comListstringDic.Remove(aa);
                if (comListstringDic.Count > 0)
                {
                    comboBox2.DataSource = new BindingSource() { DataSource = comListstringDic };
                }
                else
                {
                    comboBox2.DataSource= null;
                }
                label6.Text = "0";
            }
        }

        private void button14_Click(object sender, EventArgs e)//发送消息
        {
            if (comboBox2.Text.Length > 0&&NowClientClass.CIfConn)
            {
                if (radioButton4.Checked)//十六进制发送消息
                {
                    if ((textBox6.Text.Length % 2) != 0)
                        textBox6.Text = textBox6.Text.Insert(textBox6.Text.Length - 1, 0.ToString());
                    byte[] returnBytes = new byte[textBox6.Text.Length / 2];
                    for (int i = 0; i < returnBytes.Length; i++)
                        returnBytes[i] = Convert.ToByte(textBox6.Text.Substring(i * 2, 2), 16);
                    //根据客户端IP端口找到字典集合socket
                    Send(NowClientClass.CSocket, returnBytes);
                }
                else
                {
                    Send(NowClientClass.CSocket, Encoding.Default.GetBytes(textBox6.Text));
                }
                NowClientClass.CRecvStr += (DateTime.Now +"【发送】数据 :" + textBox6.Text + "\r\n");
                textBox7.Text = NowClientClass.CRecvStr;


            }
        }

        private void textBox5_KeyPress(object sender, KeyPressEventArgs e)
        {
            //如果输入的不是退格和数字,则屏蔽输入
            if (!(e.KeyChar == '\b' || (e.KeyChar >= '0' && e.KeyChar <= '9')))
            {
                e.Handled = true;
            }
        }

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值