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

简介: 服务端 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.

服务端

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];
        }
    }
}

目录
相关文章
|
网络协议 物联网 开发者
NB-IoT 通信之 TCP 收发数据 | 学习笔记
快速学习 NB-IoT 通信之 TCP 收发数据
NB-IoT 通信之 TCP 收发数据 | 学习笔记
|
传感器 数据采集 JSON
RS232/RS485转4G DTU 上传基于Modbus协议的温湿度传感器数据到远程TCP服务器
RS232/RS485转4G DTU 上传基于Modbus协议的温湿度传感器数据到远程TCP服务器
714 0
RS232/RS485转4G DTU 上传基于Modbus协议的温湿度传感器数据到远程TCP服务器
|
7月前
|
网络协议 开发者 Python
tcp/ip模型中,帧是第几层的数据单元?
在网络通信的世界中,TCP/IP模型以其高效和可靠性而著称。这个模型是现代互联网通信的基石,它定义了数据在网络中如何被传输和接收。其中,一个核心的概念是数据单元的层级,特别是“帧”在这个模型中的位置。今天,我们就来说一下TCP/IP模型中帧的概念,以及它作为数据单元在哪一层中扮演着关键角色。
|
存储 监控 网络协议
搞了半天,终于弄懂了TCP Socket数据的接收和发送,太难
本文将从上层介绍Linux上的TCP/IP栈是如何工作的,特别是socket系统调用和内核数据结构的交互、内核和实际网络的交互。写这篇文章的部分原因是解释监听队列溢出(listen queue overflow)是如何工作的,因为它与我工作中一直在研究的一个问题相关。 建好的连接怎么工作 先从建好的连接开始介绍,稍后将解释新建连接是如何工作的。
搞了半天,终于弄懂了TCP Socket数据的接收和发送,太难
|
JSON 网络协议 Android开发
【Android 逆向】Android 逆向通用工具开发 ( Android 端远程命令工具 | Android 端可执行程序的 main 函数操作 | TCP 协议服务器建立 | 接收客户端数据 )
【Android 逆向】Android 逆向通用工具开发 ( Android 端远程命令工具 | Android 端可执行程序的 main 函数操作 | TCP 协议服务器建立 | 接收客户端数据 )
213 0
【Android 逆向】Android 逆向通用工具开发 ( Android 端远程命令工具 | Android 端可执行程序的 main 函数操作 | TCP 协议服务器建立 | 接收客户端数据 )
|
网络协议 Java
【Java 网络编程】TCP 传输机制 ( 数据拆分 | 排序 | 顺序发送 | 顺序组装 | 超时重发 )
【Java 网络编程】TCP 传输机制 ( 数据拆分 | 排序 | 顺序发送 | 顺序组装 | 超时重发 )
268 0
【Java 网络编程】TCP 传输机制 ( 数据拆分 | 排序 | 顺序发送 | 顺序组装 | 超时重发 )
|
网络协议
tcp回显客户端发送的数据
客户端: import socket tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tcp_socket.connect(('127.
973 0