C# TcpListener的编程要点
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Threading; using System.Windows.Forms; namespace Server { public partial class Form1 : Form { public Form1() { InitializeComponent(); listener = new TcpListener(IPAddress.Any, 9009);// 端口根据需要确定 listener.Start(); // 后台线程1:用于接收tcp连接请求,并将网络流加入列表。随主线程的退出而退出。 new Thread(() => { while (true) { Thread.Sleep(100);// 可以根据需要设置时间 if (!listener.Pending()) { continue; } var client = listener.AcceptTcpClient(); // 下面属性根据需要进行设置 // client.ReceiveBufferSize // client.ReceiveTimeout // client.SendBufferSize // client.SendTimeout if (!client.Connected) { continue; } streams.Add(client.GetStream()); } }) { IsBackground = true }.Start(); // 后台线程2:用于接收请求,并作出响应。随主线程的退出而退出。 new Thread(() => { while (true) { Thread.Sleep(100);// 可以根据需要设置时间 if (streams == null || streams.Count == 0) { continue; } streams = streams.Where(s => s.CanRead && s.CanWrite).ToList(); foreach (var stream in streams.Where(stream => stream.CanRead && stream.CanWrite)) { AsyncReceiveBytes(stream, s => { // todo:对result进行解码 // todo:对收到指令进行逻辑判断,得出待响应的C#对象 AsyncSendBytes(s, new byte[0]); // todo:将待响应的C#对象转换成字节数组,替换new byte[0]。 }); } } }) { IsBackground = true }.Start(); } // 发送事件和目标的入口 public void SendEventAndTarget() { if (streams == null || streams.Count == 0) { return; } streams = streams.Where(s => s.CanRead && s.CanWrite).ToList(); foreach (var stream in streams.TakeWhile(stream => stream.CanWrite)) { AsyncSendBytes(stream, new byte[0]);// todo:这里将待发送的C#对象转换的字节数组替换new byte[0]。 } } private static void AsyncReceiveBytes(NetworkStream stream, Action<NetworkStream> callback) { // 短时后台线程:用于处理网络流的读操作,处理完成后即归还线程池。 // 每个网络流都会分配一个线程。 //ThreadPool.SetMaxThreads();根据需要设置。 ThreadPool.QueueUserWorkItem(delegate { var buffer = new byte[1024];// 1024:根据需要进行设置。 var result = new byte[0]; do { var a = stream.Read(buffer, 0, buffer.Length); result = result.Concat(buffer.Take(a)).ToArray(); } while (stream.DataAvailable); callback(stream); }); } private static void AsyncSendBytes(NetworkStream stream, byte[] bytes) { // 短时后台线程:用于处理网络流的写操作,处理完成后即归还线程池。 // 每个网络流都会分配一个线程。 //ThreadPool.SetMaxThreads();根据需要设置。 ThreadPool.QueueUserWorkItem(delegate { try { stream.Write(bytes, 0, bytes.Count()); } catch (Exception) { MessageBox.Show("远程主机主动断开此连接!");// 也可以做其它处理。 } }); } private readonly TcpListener listener; // 网络流列表 private List<NetworkStream> streams = new List<NetworkStream>(); } }
找时间在项目中应用后,再总结一下。