TCP服务器的实现与取消机制

网络编程中,TCP服务器是一个常见的组件,用于处理客户端的连接和数据传输。然而,在某些情况下,需要能够随时停止服务器的运行,这就需要引入取消机制。本文将介绍如何使用C#创建一个支持取消的TCP服务器,包括监听连接、读取数据和响应客户端请求的实现方式。

监听连接

TCP服务器的核心功能之一是监听来自客户端的连接请求。在C#中,可以使用TcpListener类来实现这一功能。服务器需要在一个指定的端口上监听,当有客户端尝试连接时,服务器可以接受这个连接并创建一个TcpClient对象来与客户端进行通信。

读取数据

一旦服务器与客户端建立了连接,下一步就是读取客户端发送的数据。这通常通过读取TcpClient的网络流来实现。服务器需要不断地检查是否有可用的数据可以读取,如果有,就将这些数据读取到缓冲区中,并将其转换为字符串或其他适当的格式。

响应客户端请求

在接收到客户端的数据后,服务器可以根据需要对这些数据进行处理,并将处理结果发送回客户端。这通常涉及到将数据写入到与客户端连接的网络流中。在处理完所有请求后,服务器应该关闭与客户端的连接。

取消机制

在某些情况下,可能需要在服务器运行过程中随时停止它。为了实现这一点,可以引入一个取消机制。在C#中,可以使用CancellationToken类来实现这一功能。服务器可以在运行过程中定期检查这个取消令牌的状态,如果它被设置为取消状态,服务器就应该停止当前的操作并关闭所有连接。

示例代码

public static class TcpServer { private const int SleepTimeout = 50; // milliseconds public static Task Run(int port, CancellationToken cancellation, Action, TcpClient, CancellationToken> onLineReceived) { return Accept(port, cancellation, (client, token) => { var receivedLines = new List(); while (!cancellation.IsCancellationRequested && client.Connected) { var available = client.Available; if (available == 0) { Thread.Sleep(SleepTimeout); continue; } var buffer = new byte[available]; client.GetStream().Read(buffer, 0, available); var newData = Encoding.UTF8.GetString(buffer); bool newLine; AppendLines(receivedLines, newData, out newLine); if (newLine) onLineReceived(receivedLines, client, cancellation); } client.Close(); }); } private static Task Accept(int port, CancellationToken cancellation, Action onClientAccepted) { var childTasks = new List(); var listener = new TcpListener(IPAddress.Any, port); listener.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); listener.Start(); return Task.Factory.StartNew(() => { while (!cancellation.IsCancellationRequested) { if (!listener.Pending()) { Thread.Sleep(SleepTimeout); continue; } var client = listener.AcceptTcpClient(); var childTask = new Task(() => onClientAccepted(client, cancellation)); childTasks.Add(childTask); childTask.ContinueWith(t => childTasks.Remove(t)); childTask.Start(); } }, cancellation).ContinueWith(t => { Task.WaitAll(childTasks.ToArray()); listener.Stop(); }); } private static void AppendLines(List lines, string newData, out bool newLine) { int i; int pos = 0; string line; newLine = false; for (i = pos; i < newData.Length; i++) { if (newData[i] == '\n') { line = (i > 0 && newData[i - 1] == '\r') ? newData.Substring(pos, i - pos - 1) : newData.Substring(pos, i - pos); if (lines.Count == 0) lines.Add(line); else { if (newLine) lines.Add(line); else lines[lines.Count - 1] = lines[lines.Count - 1] + line; } newLine = true; pos = i + 1; } } line = newData.Substring(pos); if (!string.IsNullOrEmpty(line)) lines[lines.Count - 1] = lines[lines.Count - 1] + line; } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485