通过异步方式发送和接收数据(tcp异步收发数据)

2022-05-09 11:44:45 浏览数 (1)

服务端

代码语言:javascript复制
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace TcpTest2
{
    public partial class Form1 : Form
    {
        bool isExit = false;
        System.Collections.ArrayList clientList = new System.Collections.ArrayList();
        TcpListener listener;
        delegate void SetListBoxCallBack(string str);
        SetListBoxCallBack setListCallBack;
        delegate void SetRecvBoxCallBack(string str);
        SetRecvBoxCallBack setRecvBoxCallBack;
        delegate void SetComboBoxCallBack(string str);
        SetComboBoxCallBack setComboBoxCallBack;
        delegate void RemoveComboBoxCallBack(DataReadWrite drw);
        RemoveComboBoxCallBack removeComboBoxCallBack;
        ManualResetEvent allDone = new ManualResetEvent(false);//通知一个或多个正在等待的线程已发生事件

        public Form1()
        {
            InitializeComponent();
            setListCallBack = new SetListBoxCallBack(setListBox);
            setRecvBoxCallBack = new SetRecvBoxCallBack(this.setRichBox);
            setComboBoxCallBack = new SetComboBoxCallBack(this.setComboBox);
            removeComboBoxCallBack = new RemoveComboBoxCallBack(this.removeComboBoxItem);
            button2.Enabled = false;
        }
        private void setListBox(string str)
        {
            listBox1.Items.Add(str);
            listBox1.SelectedIndex = listBox1.Items.Count - 1;
            listBox1.ClearSelected();
        }
        private void setRichBox(string str)
        {
            richTextBox1.AppendText(str);
        }
        private void setComboBox(object obj)
        {
            comboBox1.Items.Add(obj);
        }
        private void removeComboBoxItem(DataReadWrite drw)
        {
            int index = clientList.IndexOf(drw);
            comboBox1.Items.Remove(index);
        }
        private void button1_Click(object sender, EventArgs e)
        {
            Thread t = new Thread(new ThreadStart(AcceptConn));//新建线程建立侦听
            t.Start();
            button1.Enabled = false;
            button2.Enabled = true;
        }
        private void AcceptConn()
        {
            IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());
            listener = new TcpListener(ips[0], 51888);
            listener.Start();
            while (isExit == false)
            {
                allDone.Reset();//将事件状态设置为非终止状态
                AsyncCallback callback = new AsyncCallback(acceptTcpClientCallBack);
                listBox1.Invoke(setListCallBack, "开始等待连接");
                listener.BeginAcceptTcpClient(callback, listener);//开始一个异步操作,来接受一个传入的连接尝试
                allDone.WaitOne();//阻止当前线程,直到allDone.Set()之后继续运行
            }
        }
        /// <summary>
        /// 接收到一个请求,此方法运行在异步线程上
        /// </summary>
        /// <param name="iar"></param>
        private void acceptTcpClientCallBack(IAsyncResult iar)
        {
            allDone.Set();
            TcpListener listener = (TcpListener)iar.AsyncState;
            TcpClient client = listener.EndAcceptTcpClient(iar);//异步接受传入的连接并创建新的TcpClient来处理远程主机通信
            listBox1.Invoke(setListCallBack, "已接受客户连接:"   client.Client.RemoteEndPoint);
            comboBox1.Invoke(setComboBoxCallBack, client.Client.RemoteEndPoint.ToString());
            DataReadWrite drw = new DataReadWrite(client);
            clientList.Add(drw);
            SendString(drw, "服务器已接受连接");
            drw.netStream.BeginRead(drw.read, 0, drw.read.Length, new AsyncCallback(readCallBack), drw);//开始异步读取数据
        }
        /// <summary>
        /// 发送字符串
        /// </summary>
        /// <param name="drw"></param>
        /// <param name="str"></param>
        private void SendString(DataReadWrite drw, string str)
        {
            drw.write = Encoding.UTF8.GetBytes(str   "rn");
            drw.netStream.BeginWrite(drw.write, 0, drw.write.Length, new AsyncCallback(SendCallBack), drw);//开始向流异步写入数据
            drw.netStream.Flush();
            listBox1.Invoke(setListCallBack, string.Format("向{0}发送{1}", drw.client.Client.RemoteEndPoint, str));
        }
        /// <summary>
        /// 发送字符串完毕
        /// </summary>
        /// <param name="iar"></param>
        private void SendCallBack(IAsyncResult iar)
        {
            DataReadWrite drw = (DataReadWrite)iar.AsyncState;
            drw.netStream.EndWrite(iar);//异步写入数据结束
        }
        /// <summary>
        /// 接收字符串
        /// </summary>
        /// <param name="iar"></param>
        private void readCallBack(IAsyncResult iar)
        {
            DataReadWrite drw = (DataReadWrite)iar.AsyncState;
            int recv = drw.netStream.EndRead(iar);//异步读取结束
            richTextBox1.Invoke(setRecvBoxCallBack, string.Format("来自{0}:{1}", drw.client.Client.RemoteEndPoint, Encoding.UTF8.GetString(drw.read, 0, recv)));
            if (isExit == false)
            {
                drw.InitReadArr();
                drw.netStream.BeginRead(drw.read, 0, drw.read.Length, readCallBack, drw);//无限循环的读取下去
            }
        }
        /// <summary>
        /// 断开连接,没写代码
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {

        }
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            int index = comboBox1.SelectedIndex;
            if (index != -1)
            {
                DataReadWrite drw = (DataReadWrite)clientList[index];
                SendString(drw, richTextBox2.Text);
                richTextBox2.Clear();
            }
        }
    }
/// <summary>
/// 数据输入输出基础类
/// </summary>
    public class DataReadWrite
    {
        public TcpClient client;
        public NetworkStream netStream;
        public byte[] read;
        public byte[] write;
        public DataReadWrite(TcpClient client)
        {
            this.client = client;
            netStream = client.GetStream();//获取用于发送和接受数据的流
            read = new byte[client.ReceiveBufferSize];
            write = new byte[client.SendBufferSize];
        }
        public void InitReadArr()
        {
            read = new byte[client.ReceiveBufferSize];
        }
        public void InitWriterArr()
        {
            write = new byte[client.SendBufferSize];
        }
    }
}

客户端

代码语言:javascript复制
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace TcpTest
{
    public partial class Form1 : Form
    {
        bool isExit = false;
        delegate void SetListBoxCallBack(string str);
        SetListBoxCallBack setListCallBack;
        delegate void SetRecvBoxCallBack(string str);
        SetRecvBoxCallBack setRecvBoxCallBack;
        TcpClient client;
        NetworkStream netStream;
        ManualResetEvent allDone = new ManualResetEvent(false);//通知一个或多个正在等待的线程已发生事件

        public Form1()
        {
            InitializeComponent();
            setListCallBack = new SetListBoxCallBack(setListBox);
            setRecvBoxCallBack = new SetRecvBoxCallBack(this.setRecvBox);
        }
        private void setListBox(string str)
        {
            listBox1.Items.Add(str);
            listBox1.SelectedIndex = listBox1.Items.Count - 1;
            listBox1.ClearSelected();
        }
        private void setRecvBox(string str)
        {
            richTextBox1.AppendText(str);
        }
        /// <summary>
        /// 连接服务器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            client = new TcpClient(AddressFamily.InterNetwork);
            AsyncCallback requestCallBack = new AsyncCallback(this.requestCallBack);//引用在相应异步操作完成时调用的方法
            allDone.Reset();//将事件线程设置为非终止状态
            client.BeginConnect(IPAddress.Parse(textBox1.Text.Trim()), 51888, requestCallBack, client);
            listBox1.Invoke(setListCallBack, string.Format("本地终结点:{0}", client.Client.LocalEndPoint));
            listBox1.Invoke(setListCallBack, string.Format("开始与服务器连接"));
            allDone.WaitOne();//阻止当前线程,直到allDone.Set()之后继续运行
        }

        /// <summary>
        /// 连接服务器成功
        /// </summary>
        /// <param name="iar">表示异步操作的状态</param>
        private void requestCallBack(IAsyncResult iar)
        {
            allDone.Set();
            client = (TcpClient)iar.AsyncState;
            client.EndConnect(iar);
            listBox1.Invoke(setListCallBack, string.Format("与服务器{0}连接成功", client.Client.RemoteEndPoint));
            netStream = client.GetStream();
            DataRead dr = new DataRead(netStream, client.ReceiveBufferSize);//client.ReceiveBufferSize接收缓冲区的大小
            netStream.BeginRead(dr.msg, 0, dr.msg.Length, new AsyncCallback(readCallBack), dr);//开始接受数据
        }
        /// <summary>
        /// 接收数据完成
        /// </summary>
        /// <param name="iar"></param>
        private void readCallBack(IAsyncResult iar)
        {
            DataRead dr = (DataRead)iar.AsyncState;
            int recv = dr.netStream.EndRead(iar);
            richTextBox2.Invoke(setRecvBoxCallBack, Encoding.UTF8.GetString(dr.msg, 0, recv));
            if (isExit == false)
            {
                dr = new DataRead(netStream, client.ReceiveBufferSize);//此处有些不妥,可参照服务端的做法
                netStream.BeginRead(dr.msg, 0, dr.msg.Length, this.readCallBack, dr);//无限的接收下去
            }

        }
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            sendString(richTextBox2.Text);
            richTextBox2.Clear();
        }
        /// <summary>
        /// 异步发送数据
        /// </summary>
        /// <param name="str"></param>
        private void sendString(string str)
        {
            byte[] bytesdata = Encoding.UTF8.GetBytes(str   "rn");
            netStream.BeginWrite(bytesdata, 0, bytesdata.Length, new AsyncCallback(sendCallBack), netStream);
            netStream.Flush();
        }
        /// <summary>
        /// 异步发送数据完成
        /// </summary>
        /// <param name="iar"></param>
        private void sendCallBack(IAsyncResult iar)
        {
            netStream.EndWrite(iar);

        }
    }
    /// <summary>
    /// 接收数据基础类
    /// </summary>
    public class DataRead
    {
        public NetworkStream netStream;
        public byte[] msg;
        public DataRead(NetworkStream ns, int buffersize)
        {
            this.netStream = ns;
            this.msg = new byte[buffersize];
        }
    }
}

0 人点赞