高性能TcpServer(C#) - 2.创建高性能Socket服务器SocketAsyncEventArgs的实现(IOCP)
高性能TcpServer(C#) - 2.创建高性能Socket服务器SocketAsyncEventArgs的实现(IOCP)
高性能TcpServer(C#) - 3.命令通道(处理:掉包,粘包,垃圾包)
高性能TcpServer(C#) - 4.文件通道(处理:文件分包,支持断点续传)
代码解析
SocketAsyncEventArgs对象管理 -- 用于CheckOut/CheckIn SocketAsyncEventArgs对象
SocketArgsPool socketArgsPool = new SocketArgsPool(MAX_CLIENTCOUNT);
this.m_EventArgs = this.m_socketArgsPool.CheckOut();// 初始化对象
this.m_bufferPool.CheckIn(m_EventArgs);// 回收对象
SocketArgsBufferPool对象管理 -- 用于CheckOut/CheckIn SocketAsyncEventArgs的Buffer
SocketArgsBufferPool bufferPool = new SocketArgsBufferPool(MAX_CLIENTCOUNT, MAX_CLIENTBUFFERSIZE);
this.m_bufferPool.CheckOut(this.m_EventArgs);// 设置setBuffer
this.m_bufferPool.CheckIn(m_EventArgs);// 回收对象
SocketEntityPool对象管理 -- 用于CheckOut/CheckIn SocketEntity
SocketEntityPool socketEntityPool = new SocketEntityPool(MAX_CLIENTCOUNT, MAX_CLIENTBUFFERSIZE);// 初始化
m_socketEntity = this.m_socketEntityPool.CheckOut();
m_socketEntity.SocketClient = socket;
m_bufferRecv = m_socketEntity.BufferRecv; m_bufferRecv.Clear();// 每个client的接收缓冲区
m_handle = m_socketEntity.ProtocolHandle;// 每个client的处理类
m_analysis = m_socketEntity.ProtocolAnalysis;// 每个client的解析类
this.m_socketEntityPool.CheckIn(socketEntity);// 回收对象
部分代码
服务器监听和接收客户端连接
public void Start(int port)
{
IPEndPoint ipEP = new IPEndPoint(IPAddress.Any, port);
this.m_listenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.m_listenerSocket.Bind(ipEP);
this.m_listenerSocket.Listen(100);
ListenForConnection(m_listenerArgs);
}
void ListenForConnection(SocketAsyncEventArgs args)
{
lock (this)
{
args.AcceptSocket = null;
m_listenerSocket.InvokeAsyncMethod(new SocketAsyncMethod(m_listenerSocket.AcceptAsync), AcceptAsyncCompleted, args);
}
}
void AcceptAsyncCompleted(object sender, SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.OperationAborted)
{
CLogHelp.AppendLog("[Error] AcceptAsyncCompleted:SocketError.OperationAborted");
return; //Server was stopped
}
if (e.SocketError == SocketError.Success)
{
Socket acceptSocket = e.AcceptSocket;
if (acceptSocket != null)
{
if (connections + 1 <= MAX_CLIENTCOUNT)
{
IPEndPoint clientEP = (IPEndPoint)acceptSocket.RemoteEndPoint;
sn = String.Format("{0}:{1}", clientEP.Address.ToString(), clientEP.Port);
lock (LockIndex)
{
connections = Interlocked.Increment(ref connections);
Program.AddMessage("已连接,sn:" + sn + ",当前连接数:" + CServerIntance.connections.ToString());
}
CSocketDAO socketDao = new CSocketDAO(socketArgsPool, bufferPool, socketEntityPool, acceptSocket, sn);
CSingleton<CClientMgr>.GetInstance().AddOnlineClient(socketDao);
}
else
{
Program.AddMessage("超过最大连接数:" + MAX_CLIENTCOUNT.ToString() + ",拒接连接");
}
}
}
//continue to accept!
ListenForConnection(e);
}
服务器数据处理
void ReceiveAsyncCompleted(object sender, SocketAsyncEventArgs e)
{
if (!this.m_connected) return;
try
{
m_EventArgs = e;
if (m_EventArgs.BytesTransferred == 0)
{
SocketCatchError("BytesTransferred=0"); //Graceful disconnect
return;
}
if (m_EventArgs.SocketError != SocketError.Success)
{
SocketCatchError("SocketError=" + (e.SocketError).ToString()); //NOT graceful disconnect
return;
}
//数据存储
recvTime = DateTime.Now;
m_bufferRecv.Put(e);
m_analysis.BagStatus = CProtocolAnalysis.EBagStatus.BagNone;
// 粘包处理
while (m_bufferRecv.HasRemaining())
{
// 掉包处理
if (CProtocolAnalysis.EBagStatus.BagLost == m_analysis.BagStatus) break;
m_handle.Process(m_bufferRecv, m_analysis, m_strSn);// 数据解析(垃圾包处理)
if (string.IsNullOrEmpty(m_strUid))
{
if (!string.IsNullOrEmpty(m_analysis.Uid))
{
m_strUid = m_analysis.Uid;
CSingleton<CClientMgr>.GetInstance().AddClientUid(m_strUid, m_strSn, this);
}
}
if (m_analysis.WhetherToSend)
{
string data = CProtocolBase.GetProtocol(m_analysis);
SendRealTime(data);
}
}
ListenForData(e);
}
catch (Exception ex)
{
CLogHelp.AppendLog("[Error] ReceiveAsyncCompleted,errmsg:" + ex.Message);
}
}
最新文章
- Windows程序设再读笔记01-起步
- Linux内核设计第三周——构造一个简单的Linux系统
- salt进程查看插件&salt批量创建用户
- ***Linux文件夹文件创建、删除、改名
- 打造私有的DNS 服务
- Java5、Java6、Java7的新特性
- VS2012远程调试(winform+web 远程调试)
- [转]让ORACLE LIKE 时不区分大小写
- Hibernate与数据库分表
- struts2 I18n问题 国际化
- 【转】iOS应用崩溃日志揭秘
- web安全记录
- QListWidget的QComboBox下拉列表添加复选框及消息处理
- Web Service简单入门示例
- (GO_GTD_2)基于OpenCV和QT,建立Android图像处理程序
- 利用FT232实现USB转串口
- Http请求-get和post的区别
- Shiro会话管理器与验证码实现(十四)
- InfluxDB 常用命令
- Android和IOS开发学习路线
热门文章
- java基础(20):Map、可变参数、Collections
- Windows Store可以下载安装Windows Terminal (Preview)
- python web框架Flask——后台登录
- JS基础语法---函数练习part3---4个练习
- export default和export的使用
- (转载)林轩田机器学习基石课程学习笔记1 — The Learning Problem
- 透过systemctl管理mysqld服务
- [视频教程] 灵活配置多版本PHP并存运行
- 『005』Web集群
- Tomcat 学习总结(1) --Servlet技术