(IOCP)-C#高性能Socket服务器的实现
2021-07-02 16:40
标签:framework eterm 服务器 lag pad 上下 opera 重复 while 引言 我一直在探寻一个高性能的Socket客户端代码。以前,我使用Socket类写了一些基于传统异步编程模型的代码(BeginSend、BeginReceive,等等)也看过很多博客的知识,在linux中有poll和epoll来实现,在windows下面 微软MSDN中也提供了SocketAsyncEventArgs这个类来实现IOCP 地址:https://msdn.microsoft.com/zh-cn/library/system.net.sockets.socketasynceventargs.aspx NET Framework中的APM也称为Begin/End模式。这是因为会调用Begin方法来启动异步操作,然后返回一个IAsyncResult 对象。可以选择将一个代理作为参数提供给Begin方法,异步操作完成时会调用该方法。或者,一个线程可以等待 IAsyncResult.AsyncWaitHandle。当回调被调用或发出等待信号时,就会调用End方法来获取异步操作的结果。这种模式很灵活,使用相对简单,在 .NET Framework 中非常常见。 但是,您必须注意,如果进行大量异步套接字操作,是要付出代价的。针对每次操作,都必须创建一个IAsyncResult对象,而且该对象不能被重复使用。由于大量使用对象分配和垃圾收集,这会影响性能。为了解决这个问题,新版本提供了另一个使用套接字上执行异步I/O的方法模式。这种新模式并不要求为每个套接字操作分配操作上下文对象。 代码下载:http://download.csdn.net/detail/zhujunxxxxx/8431289这里的代码优化了的 目标 在上面微软提供的例子我觉得不是很完整,没有具体一个流程,只是受到客户端消息后发送相同内容给客户端,初学者不容易看懂流程,因为我花了一天的时间来实现一个功能齐全的IOCP服务器, 效果如下
代码 首先是ICOPServer.cs 这个类是IOCP服务器的核心类,目前这个类是网络上比较全的代码,MSDN上面的例子都没有我的全 (IOCP)-C#高性能Socket服务器的实现 标签:framework eterm 服务器 lag pad 上下 opera 重复 while 原文地址:https://www.cnblogs.com/Leo_wl/p/9920851.htmlC#高性能Socket服务器的实现(IOCP)
https://www.jianshu.com/p/c65c0eb59f22
using?System;??
using?System.Collections.Generic;??
using?System.Linq;??
using?System.Text;??
using?System.Net.Sockets;??
using?System.Net;??
using?System.Threading;??
namespace?ServerTest??
{??
///???
///?IOCP?SOCKET服务器??
///???
public?class?IOCPServer?:?IDisposable??
????{??
const?int?opsToPreAlloc?=?2;??
????????#region?Fields??
///???
///?服务器程序允许的最大客户端连接数??
///???
private?int?_maxClient;??
///???
///?监听Socket,用于接受客户端的连接请求??
///???
private?Socket?_serverSock;??
///???
///?当前的连接的客户端数??
///???
private?int?_clientCount;??
///???
///?用于每个I/O?Socket操作的缓冲区大小??
///???
private?int?_bufferSize?=?1024;??
///???
///?信号量??
///???
????????Semaphore?_maxAcceptedClients;??
///???
///?缓冲区管理??
///???
????????BufferManager?_bufferManager;??
///???
///?对象池??
///???
????????SocketAsyncEventArgsPool?_objectPool;??
private?bool?disposed?=?false;??
????????#endregion??
????????#region?Properties??
///???
///?服务器是否正在运行??
///???
public?bool?IsRunning?{?get;?private?set;?}??
///???
///?监听的IP地址??
///???
public?IPAddress?Address?{?get;?private?set;?}??
///???
///?监听的端口??
///???
public?int?Port?{?get;?private?set;?}??
///???
///?通信使用的编码??
///???
public?Encoding?Encoding?{?get;?set;?}??
????????#endregion??
????????#region?Ctors??
///???
///?异步IOCP?SOCKET服务器??
///???
///?监听的端口??
///?最大的客户端数量??
public?IOCPServer(int?listenPort,int?maxClient)??
:this(IPAddress.Any,?listenPort,?maxClient)??
????????{??
????????}??
///???
///?异步Socket?TCP服务器??
///???
///?监听的终结点??
///?最大客户端数量??
public?IOCPServer(IPEndPoint?localEP,?int?maxClient)??
:this(localEP.Address,?localEP.Port,maxClient)??
????????{??
????????}??
///???
///?异步Socket?TCP服务器??
///???
///?监听的IP地址??
///?监听的端口??
///?最大客户端数量??
public?IOCPServer(IPAddress?localIPAddress,?int?listenPort,?int?maxClient)??
????????{??
this.Address?=?localIPAddress;??
this.Port?=?listenPort;??
this.Encoding?=?Encoding.Default;??
????????????_maxClient?=?maxClient;??
_serverSock?=new?Socket(localIPAddress.AddressFamily,?SocketType.Stream,?ProtocolType.Tcp);??
_bufferManager?=new?BufferManager(_bufferSize?*?_maxClient?*?opsToPreAlloc,_bufferSize);??
_objectPool?=new?SocketAsyncEventArgsPool(_maxClient);??
_maxAcceptedClients?=new?Semaphore(_maxClient,?_maxClient);???
????????}??
????????#endregion??
????????#region?初始化??
///???
///?初始化函数??
///???
public?void?Init()??
????????{??
//?Allocates?one?large?byte?buffer?which?all?I/O?operations?use?a?piece?of.??This?gaurds???
//?against?memory?fragmentation??
????????????_bufferManager.InitBuffer();??
//?preallocate?pool?of?SocketAsyncEventArgs?objects??
????????????SocketAsyncEventArgs?readWriteEventArg;??
for?(int?i?=?0;?i??startTickCount?+?timeout)??
????????????????{??
//throw?new?Exception("Timeout.");??
????????????????}??
try??
????????????????{??
????????????????????sent?+=?socket.Send(buffer,?offset?+?sent,?size?-?sent,?SocketFlags.None);??
????????????????}??
catch?(SocketException?ex)??
????????????????{??
if?(ex.SocketErrorCode?==?SocketError.WouldBlock?||??
????????????????????ex.SocketErrorCode?==?SocketError.IOPending?||??
????????????????????ex.SocketErrorCode?==?SocketError.NoBufferSpaceAvailable)??
????????????????????{??
//?socket?buffer?is?probably?full,?wait?and?try?again??
????????????????????????Thread.Sleep(30);??
????????????????????}??
else??
????????????????????{??
throw?ex;?//?any?serious?error?occurr??
????????????????????}??
????????????????}??
}while?(sent??0?&&?e.SocketError?==?SocketError.Success)??
????????????{??
//?检查远程主机是否关闭连接??
if?(e.BytesTransferred?>?0)??
????????????????{??
????????????????????Socket?s?=?(Socket)e.UserToken;??
//判断所有需接收的数据是否已经完成??
if?(s.Available?==?0)??
????????????????????{??
//从侦听者获取接收到的消息。???
//String?received?=?Encoding.ASCII.GetString(e.Buffer,?e.Offset,?e.BytesTransferred);??
//echo?the?data?received?back?to?the?client??
//e.SetBuffer(e.Offset,?e.BytesTransferred);??
byte[]?data?=?new?byte[e.BytesTransferred];??
Array.Copy(e.Buffer,?e.Offset,?data,?0,?data.Length);//从e.Buffer块中复制数据出来,保证它可重用??
string?info=Encoding.Default.GetString(data);??
Log4Debug(String.Format("收到?{0}?数据为?{1}",s.RemoteEndPoint.ToString(),info));??
//TODO?处理数据??
//增加服务器接收的总字节数。??
????????????????????}??
if?(!s.ReceiveAsync(e))//为接收下一段数据,投递接收请求,这个函数有可能同步完成,这时返回false,并且不会引发SocketAsyncEventArgs.Completed事件??
????????????????????{??
//同步接收时处理接收完成事件??
????????????????????????ProcessReceive(e);??
????????????????????}??
????????????????}??
????????????}??
else??
????????????{??
????????????????CloseClientSocket(e);??
????????????}??
????????}??
????????#endregion??
????????#region?回调函数??
///???
///?当Socket上的发送或接收请求被完成时,调用此函数??
///???
///?激发事件的对象??
///?与发送或接收完成操作相关联的SocketAsyncEventArg对象??
private?void?OnIOCompleted(object?sender,?SocketAsyncEventArgs?e)??
????????{??
//?Determine?which?type?of?operation?just?completed?and?call?the?associated?handler.??
switch?(e.LastOperation)??
????????????{??
case?SocketAsyncOperation.Accept:??
????????????????????ProcessAccept(e);??
break;??
case?SocketAsyncOperation.Receive:??
????????????????????ProcessReceive(e);??
break;??
default:??
throw?new?ArgumentException("The?last?operation?completed?on?the?socket?was?not?a?receive?or?send");??
????????????}??
????????}??
????????#endregion??
????????#region?Close??
///???
///?关闭socket连接??
///???
///?SocketAsyncEventArg?associated?with?the?completed?send/receive?operation.??
private?void?CloseClientSocket(SocketAsyncEventArgs?e)??
????????{??
Log4Debug(String.Format("客户?{0}?断开连接!",((Socket)e.UserToken).RemoteEndPoint.ToString()));??
Socket?s?=?e.UserTokenas?Socket;??
????????????CloseClientSocket(s,?e);??
????????}??
///???
///?关闭socket连接??
///???
///???
///???
private?void?CloseClientSocket(Socket?s,?SocketAsyncEventArgs?e)??
????????{??
try??
????????????{??
????????????????s.Shutdown(SocketShutdown.Send);??
????????????}??
catch?(Exception)??
????????????{??
//?Throw?if?client?has?closed,?so?it?is?not?necessary?to?catch.??
????????????}??
finally??
????????????{??
????????????????s.Close();??
????????????}??
Interlocked.Decrement(ref?_clientCount);??
????????????_maxAcceptedClients.Release();??
_objectPool.Push(e);//SocketAsyncEventArg?对象被释放,压入可重用队列。??
????????}??
????????#endregion??
????????#region?Dispose??
///???
///?Performs?application-defined?tasks?associated?with?freeing,???
///?releasing,?or?resetting?unmanaged?resources.??
///???
public?void?Dispose()??
????????{??
Dispose(true);??
GC.SuppressFinalize(this);??
????????}??
///???
///?Releases?unmanaged?and?-?optionally?-?managed?resources??
///???
///?true?to?release???
///?both?managed?and?unmanaged?resources;?false???
///?to?release?only?unmanaged?resources.??
protected?virtual?void?Dispose(bool?disposing)??
????????{??
if?(!this.disposed)??
????????????{??
if?(disposing)??
????????????????{??
try??
????????????????????{??
????????????????????????Stop();??
if?(_serverSock?!=?null)??
????????????????????????{??
_serverSock?=null;??
????????????????????????}??
????????????????????}??
catch?(SocketException?ex)??
????????????????????{??
//TODO?事件??
????????????????????}??
????????????????}??
disposed?=true;??
????????????}??
????????}??
????????#endregion??
public?void?Log4Debug(string?msg)??
????????{??
Console.WriteLine("notice:"+msg);??
????????}??
????}??
}
上一篇:c# 语法 字符串内插