做CS的开发一直都是这样的方式:
server端用 C++编写,采用IOCP机制处理大量客户端连接、数据接收发送的问题
client端用 C++ 或C# 写,没什么特殊要求。
最近工作时间上比较宽裕,决定采用新的方式来处理服务端的工作: C# + SOCKET异步机制(.net里没有IOCP的直接支持)
目前正可行性分析阶段,第一步的工作:接收3W个SOCKET连接, 结果还是不错的,很快就建立起来了,速度也可以。
但是第二步测试,接收、发送数据时,就发生了点问题:
运行的SERVER程序在较短的时间内就占用了大量的内存!
我的测试环境:i3 +2G内存 + Win732位
客户端创建5000个连接,每间隔1秒种对所有的连接发送、接收一次数据。每次发送20bytes到server。
服务端与客户端不在同一台机器上
一般情况下,程序的启动内存占用为4.5M ,运行5分钟后,SERVER程序内存占用超过 100M,并且还在不停的快速增长
在一台服务器上测试(2W个连接),4个小时内,把8G内存全部用光(从任务管理器上看,使用了7.9G内存)
先看SERVER端的完整代码:(大家可以COPY到自己的IDE里直接编译)
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Net.Sockets;
- namespace TestAsyncSendMem
- {
- class Program
- {
- static TcpListener m_lisnter;
- static AsyncCallback m_acb = new AsyncCallback(DoAcceptSocketCallback);
- static void Main(string[] args)
- {
- m_lisnter = new System.Net.Sockets.TcpListener(System.Net.IPAddress.Any, 8001);
- m_lisnter.Start(5 * 1000);
- try
- {
- m_lisnter.BeginAcceptSocket(m_acb, null);
- }
- catch (Exception ex)
- {
- m_lisnter.Stop();
- m_lisnter = null;
- System.Diagnostics.Debug.WriteLine("BeginAcceptSocket err.Start fail!" + ex);
- return;
- }
- Console.WriteLine("Begin receiving connection... Press any key to quit.");
- Console.ReadKey();
- m_lisnter.Stop();
- }
- static void DoAcceptSocketCallback(IAsyncResult ar)
- {
- System.Net.Sockets.Socket s = null;
- try
- {
- s = m_lisnter.EndAcceptSocket(ar);
- }
- catch (Exception ex)
- {
- System.Diagnostics.Debug.WriteLine("End Accept socket err" + ex);
- s = null;
- }
- try
- {
- m_lisnter.BeginAcceptSocket(m_acb, null);
- }
- catch (Exception ex)
- {
- System.Diagnostics.Debug.WriteLine("after accept client socket,Re beginAcceptSocket fail." + ex);
- }
- if (s != null)
- {
- #region...
- CTcpClientSync c = new CTcpClientSync(s);
- Console.WriteLine(string.Format("accept client.{0}", c.Socket.RemoteEndPoint));
- if (c.BeginRcv() == true)
- {
- c.OnDisconnected += (CTcpClientSync client) =>
- {
- System.Diagnostics.Debug.WriteLine(string.Format("client {0} disconected", client.RemoteIP));
- };
- }
- else
- {
- c.Stop();
- System.Diagnostics.Debug.WriteLine(string.Format("accepted client {0} removed.cannot begin rcv", c.RemoteIP));
- }
- #endregion
- }
- }
- }
- public class CTcpClientSync
- {
- #region delegate