通过异步方式发送和接收数据(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]; } } }