c# tcpip 通信 Task线程接收信息

1 c# tcpip通信-用线程实现数据接收与发送

针对用定时器实现数据接收过程出现的界面卡死现象,本次采用线程进行数据接收过程。服务端和客户端如图1所示。
在这里插入图片描述图1 服务端和客户端

2 程序讲解

c# 实现服务端程序
using System;
using System.Text;
using System.Windows.Forms;
//与TCP-IP相关的命名空间
using System.Net;
using System.Net.Sockets;
//与线程相关的命名空间
using System.Threading;
using System.Threading.Tasks;

namespace C_Sharp_TCPIP_Connect_text
{
    public partial class Frm_Serviers : Form
    {
        public Frm_Serviers()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;
        }
        EndPoint endpoint;//建立一个Endpoint类型变量
        private CancellationTokenSource cts1;//建立一个线程管理变量,该值默认为false
        byte[] received_data = new byte[1024];//创建一个缓存区
        #region C#实现Tcp_Ip通信-服务端
        Socket acceptted_Socket;//创建一个Socket变量,用来存放服务端所连接的客户端的Socket
        //第一步Socket:1.1-创建服务端Socket套接字
        Socket server;//该套接字在全局中创建,在要连接时给初始化
        /// <summary>
        /// 服务端启动TCP-IP连接功能
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_TcpIp_Connect_Click(object sender, EventArgs e)
        {            
            try
            {
                //1.2-对所创建服务端Socket套接字初始化
                server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //第二步Bind:2.1-创建Endoint变量,//通过获取IP地址和端口为其初始化。为调用server变量下Bind方法提供参数
                endpoint = new IPEndPoint(IPAddress.Parse(txt_IP.Text.Trim()), int.Parse(txt_Port.Text.Trim()));//获取IP与端口
                //2.2-服务端调用Bind方法,执行绑定
                server.Bind(endpoint);
                //第三步Listen:3.1-调用server变量下Listen方法
                server.Listen(10);//参数是监听客户的的个数。如有11各客户的连接到服务端,那么只有前10各能连接上
                //第四步Accept:4.1-调用server变量下Accept方法,该方法会返回一个Socet对象,表明和哪一个客户端建立了
                acceptted_Socket = server.Accept();//等到客户端连接,当连接上时,返回所连接的客户端的Socket套接字
                #region 接下来就是实现服务端接收信息和发送信息功能
                /*可根据自己需求,在想发送的地方发送数据,在想接收信息的地方接收数据
                 *通常在建立连接时就接收数据,并发送一个连接成功的数据
                 */
                acceptted_Socket.Send(Encoding.UTF8.GetBytes("你好" + acceptted_Socket.ToString() + ",你已成功连接到服务器\n"));//向所连接的客户端发送一个连接成功消息                

                #region 开启数据接收线程
                cts1 = new CancellationTokenSource();//实例化
                Task.Factory.StartNew(Message_receive, cts1.Token);//开启线程cts1,该线程执行的方法是Message_receive
                #endregion
                #endregion
            }
            catch (Exception ex)
            {
                MessageBox.Show("错误提示:" + ex.Message);
            }                                   
        }
        /// <summary>
        /// 线程指定的方法
        /// </summary>
        private void Message_receive()
        {
            while (!cts1.IsCancellationRequested)//当cts1的值IsCancellationRequested为false时
            {
                try
                {
                    //调用Receive方法接收客户端信息,该方法返回一个int值表示所接收到的字节数。
                    int num = acceptted_Socket.Receive(received_data);//将所接收的客户端信息放到缓存区,并返回接收的字节数量
                    if (string.IsNullOrEmpty(num.ToString()))
                    {
                        Console.WriteLine("无数据");
                    }
                    else
                    {
                        rtb_ReceicedData.Text += Encoding.UTF8.GetString(received_data, 0, num);//将接收到的数据显示在桌面上
                    }
                    Thread.Sleep(1000);
                }
                catch(Exception ex)
                {
                    MessageBox.Show("错误提示:" + ex.Message);
                    break;
                }            
            }
        }
        #endregion
       
        /// <summary>
        /// 断开连接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_Tcpip_DisConnect_Click(object sender, EventArgs e)
        {
            acceptted_Socket.Close();
            cts1.Cancel();//将cts1的值IsCancellationRequested改为true
        }

        private void btn_send_Click(object sender, EventArgs e)
        {
            acceptted_Socket.Send(Encoding.UTF8.GetBytes(rtb_sendtoclient.Text));//向所连接的客户端发送一个连接成功消息                
        }

        private void btn_clear_Click(object sender, EventArgs e)
        {
            rtb_ReceicedData.Text = "";
        }

        private void btn_clear_sendmessage_Click(object sender, EventArgs e)
        {
            rtb_sendtoclient.Text = "";
        }
    }
}
c# 实现客户端程序
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
//与线程相关的命名空间
using System.Threading;
using System.Threading.Tasks;

namespace C_Sharp_TCPIP_client_text
{
    public partial class Frm_Client : Form
    {
        public Frm_Client()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;
        }

        byte[] received_data = new byte[1024];//创建一个缓存区 
        private CancellationTokenSource cts1;//建立一个线程管理变量,该值默认为false
        #region c#实现tcpip客户端功能

        //第一步Socket:1.1-创建客户端Socket套接字
        Socket client;//客户端的Socket变量

        /// <summary>
        /// 在连接按钮中实现客户端连接到指定的服务器:实现客户端的connect
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_TcpIp_Connect_Click(object sender, EventArgs e)
        {
            try
            {
                //1.2-对所创建客户端Socket套接字初始化
                client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //第二步Connect:2.1-创建Endoint变量,//通过获取IP地址和端口为其初始化。为调用client变量下Connect方法提供参数
                EndPoint endpoint = new IPEndPoint(IPAddress.Parse(txt_IP.Text.Trim()), int.Parse(txt_Port.Text.Trim()));//获取IP与端口
                //2.2-客户端调用client变量下Connect方法,该方法无返回值
                client.Connect(endpoint);
                #region 接下来就是实现服务端接收信息和发送信息功能
                /*可根据自己需求,在想发送的地方发送数据,在想接收信息的地方接收数据
                 *通常在建立连接时就接收一个数据以表示连接成功,并向服务器发送一个连接成功的数据
                 */
                client.Send(Encoding.UTF8.GetBytes("你好,服务器" + txt_IP.Text.Trim() + ",我已成功向你建立起连接\n"));
                //开启接收服务器发送的信息定时器
                #region 开启数据接收线程
                cts1 = new CancellationTokenSource();
                Task.Factory.StartNew(Message_receive, cts1.Token);//开启线程cts1,该线程执行的方法是Message_receive
                #endregion
                #endregion
            }
            catch (Exception ex)
            {
                MessageBox.Show("错误提示:" + ex.Message);
            }
            
        }
        #endregion
        private void Message_receive()
        {
            while (!cts1.IsCancellationRequested)//当cts1的值IsCancellationRequested为false时
            {
                try
                {
                    //调用Receive方法接收服务端信息,该方法返回一个int值表示所接收到的字节数。
                    int num = client.Receive(received_data);//将所接收的服务端信息放到缓存区,并返回接收的字节数量

                    if (string.IsNullOrEmpty(num.ToString()))
                    {
                        Console.WriteLine("无数据");
                    }
                    else
                    {
                        rtb_serviceData.Text += Encoding.UTF8.GetString(received_data, 0, num);//将接收到的数据显示在桌面上               
                    }
                    Thread.Sleep(1000);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("错误提示:" + ex.Message);
                    break;
                }
            }
        }     

        private void btn_Tcpip_DisConnect_Click(object sender, EventArgs e)
        {
            client.Close();
            cts1.Cancel();//将cts1的值IsCancellationRequested改为true
        }

        private void btn_clear_servicedata_rtb_Click(object sender, EventArgs e)
        {
            rtb_serviceData.Text = "";
        }

        private void btn_clear_sendingdata_rtb_Click(object sender, EventArgs e)
        {
            rtb_sendingData.Text = "";
        }

        private void btn_sendData_Click(object sender, EventArgs e)
        {
            client.Send(Encoding.UTF8.GetBytes(rtb_sendingData.Text));
        }
    }
}

3 结果

在这里插入图片描述

4 关键点

4.1 对于引用Tasks命名空间错误

using System.Threading.Tasks;会出现未引入程序集错误
在这里插入图片描述
该错误是由于.NET框架版本太低导致。可更改该项目的.NET框架,操作步骤如下:
(1)点击"解决方案"下的项目名,右键,选择 属性
在这里插入图片描述
(2)更改 目标框架 ,选择新的.NET框架,即可解决问题

在这里插入图片描述

4.2 基于Task建立的线程

4.2.1 程序流程

在这里插入图片描述
图2 基于Tasks建立实现线程流程

4.2.2 Task实现线程功能,可参考博客

https://blog.csdn.net/chenweicode/article/details/90904438

5 实例资源

5.1 通过定时器实现的数据接收(界面会卡死)

https://download.csdn.net/download/asd_8_8_8_8_8_8_asd/16338898

5.2 通过线程实现的数据接收(界面正常)

https://download.csdn.net/download/asd_8_8_8_8_8_8_asd/16523706

5.3 文档说明与实例

https://download.csdn.net/download/asd_8_8_8_8_8_8_asd/16523608
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值