通过异步方式发送和接收数据(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]; } } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统