zoukankan      html  css  js  c++  java
  • 通过异步方式发送和接收数据(tcp异步收发数据)

    服务端

    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 + "\r\n");
                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];
            }
        }
    }
    
    

    客户端

    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 + "\r\n");
                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];
            }
        }
    }
    
    
  • 相关阅读:
    深入分析String类型(一)
    创建泛型类
    XML数据的读取—数据库配置文件
    Config配置文件读写
    jQuery动画
    设置屏幕快捷键
    jQuery事件
    jQuery操作DOM
    Python 二进制文件网址
    Centos使用crontab自动定时备份mysql的脚本
  • 原文地址:https://www.cnblogs.com/liulun/p/1683172.html
Copyright © 2011-2022 走看看