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];
            }
        }
    }
    
    
  • 相关阅读:
    1105 Spiral Matrix (25分)(蛇形填数)
    1104 Sum of Number Segments (20分)(long double)
    1026 Table Tennis (30分)(模拟)
    1091 Acute Stroke (30分)(bfs,连通块个数统计)
    1095 Cars on Campus (30分)(排序)
    1098 Insertion or Heap Sort (25分)(堆排序和插入排序)
    堆以及堆排序详解
    1089 Insert or Merge (25分)
    1088 Rational Arithmetic (20分)(模拟)
    1086 Tree Traversals Again (25分)(树的重构与遍历)
  • 原文地址:https://www.cnblogs.com/liulun/p/1683172.html
Copyright © 2011-2022 走看看