TCP协议下的客户端服务器通信

在现代网络应用中,客户端与服务器之间的通信是一个核心功能。TCP(传输控制协议)因其可靠性和顺序性,成为实现这种通信的首选协议之一。本文将介绍一种简单易用的TCP协议下的客户端服务器通信实现,它不仅易于集成到项目中,而且性能出色,能够满足多线程环境下的高并发需求。

在开发过程中,经常需要处理客户端与服务器之间的数据传输问题。传统的命名管道通信虽然在某些情况下速度较快,但它要求在连接到计算机时进行身份验证,这在非域计算机上非常受限,并且需要用户在目标计算机上输入有效的系统用户名和密码才能工作。此外,命名管道的实现代码通常非常庞大。因此,开发了一种替代方案,以满足以下需求:

  • 代码简单,配置最少。
  • 多线程,能够支持数百个同时用户。
  • 不需要额外的代码“代理”和“契约”,应与常规可序列化对象兼容。
  • 不需要计算机级身份验证,这是隐含在使用TCP协议中的,因为它在操作系统的较低级别处理(与命名管道不同)。
  • 灵活性,可以在其上实现自己的认证。
  • 能够处理大型数据传输对象,例如3MB数据包。

测试应用

运行解决方案,将得到一个命令行应用程序。按下'S'键进入服务器模式,'C'键进入客户端模式,其他任何键则进入自动模式,开始向服务器发送请求。应用程序硬编码为在127.0.0.1 IP地址上发送和接收,这是本地系统;可以更改此设置以在真实网络上的不同计算机上进行测试。

使用代码

要使用代码,首先必须创建数据包,如下所示:

[Serializable()] public class Packet { public Packet() { data = new byte[3 * 1024 * 1024]; // 3 mega byte } public byte[] data { get; set; } public string Message { get; set; } public string Username { get; set; } public string Password { get; set; } public Guid SessionGuid { get; set; } public new string ToString() { return Message; } }

如所见,数据结构是常规类,而不是代理;还必须在类上放置Serializable属性,以便.NET序列化器可以处理它。

服务器端代码

NetworkServer ns = new NetworkServer(99, new ProcessPayload(serverprocess)); // 将监听端口99 ns.Start(); private static object serverprocess(object data) { Packet dp = data as Packet; if (dp != null) return HandlePacket(dp); Console.WriteLine("message not recognized"); return new ReturnPacket(); } private static object HandlePacket(Packet dp) { ReturnPacket ret = new ReturnPacket(); if (dp.SessionGuid == Guid.Empty) { // 可能需要与LDAP服务器进行身份验证 } else { // 检查sessionguid是否有效 -> 如果不是则返回失败 } ret.OK = true; ret.Message = "your msg : " + dp.Message + "\r\nreturn from server " + DateTime.Now; return ret; }

如所见,它非常简单直观。

客户端代码

NetworkClient nc = new NetworkClient("127.0.0.1", 99); // 发送到本地主机端口99 nc.Connect(); Packet p = new Packet(); ReturnPacket ret = nc.Send(p) as ReturnPacket;

性能测试

以下是在AMD K625 1.5ghz,4GB RAM,Windows 7 Home,win评分3.9的笔记本电脑上进行的性能测试结果(CPU使用率超过88%):

同时客户端数量 数据包大小 块大小 10秒内的请求数
5 ~12kb 32kb 12681
5 ~12kb 16kb 12291
5 ~12kb 4kb 11089
5 ~3mb 4kb 141
5 ~3mb 16kb 207
5 ~3mb 32kb 220

如所见,对于小数据包和大数据包,最佳性能是32KB的CHUNK_SIZE。可以提高它,例如64KB,但会得到递减的回报,并且可能(不确定)会在一些交换机和路由器上遇到问题,因为它们可能会阻止大的数据包大小。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485