/// <summary> /// 开始异步接收,同时处理传入的事件参数,里面可能有接收到的数据 /// </summary> /// <param name="e"></param> internal new void ReceiveAsync(NetEventArgs e) { if (e.BytesTransferred > 0) OnReceive(e); else base.ReceiveAsync(e); }
/// <summary>子类重载实现资源释放逻辑</summary> /// <param name="disposing">从Dispose调用(释放所有资源)还是析构函数调用(释放非托管资源)</param> protected override void OnDispose(bool disposing) { base.OnDispose(disposing); // if (_arg != null) NetEventArgs.Push(_arg); //此处不能做此操作,会导致异常,并且连接无法正常断开,移动把网络清理干净后,再将参数还回池中 var socket = Socket; if (socket != null) { //NetHelper.Close(socket, ReuseAddress); // 此时Socket可能已经销毁,不能进行Socket操作 NetHelper.Close(socket, _ReuseAddress); Socket = null; } if (_Statistics != null) { var dp = _Statistics as IDisposable; if (dp != null) { dp.Dispose(); } _Statistics = null; } if (_arg != null) { NetEventArgs.Push(_arg); } }
/// <summary> /// 已重载。设置RemoteEndPoint /// </summary> /// <param name="e"></param> protected override void OnComplete(NetEventArgs e) { IPEndPoint ep = e.RemoteEndPoint as IPEndPoint; if (ep == null || (ep.Address == IPAddress.Loopback && ep.Port == 0)) e.RemoteEndPoint = RemoteEndPoint; base.OnComplete(e); }
/// <summary>处理异步结果。</summary> /// <param name="e">事件参数</param> /// <param name="start">开始新异步操作的委托</param> /// <param name="process">处理结果的委托</param> protected virtual void Process(NetEventArgs e, Func start, Action <NetEventArgs> process) { // Socket错误由各个处理器来处理 if (e.SocketError != SocketError.Success) { OnError(e, null); return; } try { // 业务处理的任何异常,都将引发Error事件,但不会影响重新建立新的异步操作 process(e); } catch (Exception ex) { try { OnError(e, ex); } catch { } return; } // 如果不是操作取消,在处理业务完成后再开始异步操作 if (!Disposed) { start(); } }
/// <summary> /// 已重载。 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected override void OnReceived(object sender, NetEventArgs e) { if (e.BytesTransferred > 100) WriteLog("Chargen {0} [{1}]", e.RemoteEndPoint, e.BytesTransferred); else WriteLog("Chargen {0} [{1}] {2}", e.RemoteEndPoint, e.BytesTransferred, e.GetString()); }
void ShowEvent(NetEventArgs e) { //WriteLog("Completed[{4}] {0} {1} {2} [{3}]", this, e.LastOperation, e.SocketError, e.BytesTransferred, e.ID); var sb = new StringBuilder(); sb.AppendFormat("[{0}] {1} {2}://{3}", e.ID, e.LastOperation, ProtocolType, LocalEndPoint); var ep = e.RemoteIPEndPoint; //if (ep == null || ep.Address.IsAny()) ep = RemoteEndPoint; if ((ep == null || ep.Address.IsAny()) && e.LastOperation == SocketAsyncOperation.Accept && e.AcceptSocket != null) { ep = e.AcceptSocket.RemoteEndPoint as IPEndPoint; } if (ep != null && !ep.Address.IsAny()) { sb.AppendFormat("=>{0}", ep); } //sb.AppendFormat(" {0}", e.LastOperation); if (e.SocketError != SocketError.Success) { sb.AppendFormat(" {0}", e.SocketError); } sb.AppendFormat(" [{0}]", e.BytesTransferred); WriteLog(sb.ToString()); }
static void CheckNet21() { var e = new NetEventArgs(); //(e as IDisposable).Dispose(); e.AcceptSocket = null; }
/// <summary>触发完成事件。如果是异步返回,则在IO线程池中执行;如果是同步返回,则在用户线程池中执行。 /// 可能由工作线程(事件触发)调用,也可能由用户线程通过线程池线程调用。 /// 作为顶级,将会处理所有异常并调用OnError,其中OnError有能力回收参数e。 /// </summary> /// <param name="e"></param> void RaiseComplete(NetEventArgs e) { // 异步完成,减少一个计数 Interlocked.Decrement(ref _AsyncCount); if (ShowEventLog && Log.Level >= LogLevel.Debug) { ShowEvent(e); } try { // 这里直接处理操作取消 if (e.SocketError != SocketError.OperationAborted) { OnComplete(e); } else { OnError(e, null); } } catch (Exception ex) { // 都是在线程池线程里面了,不要往外抛出异常 OnError(e, ex); } }
void server_Accepted(object sender, NetEventArgs e) { TcpClientX session = e.UserToken as TcpClientX; if (session == null) return; //session.NoDelay = false; SetEvent(session); }
internal protected void CheckBufferSize(NetEventArgs e) { //Int32 n = e.BytesTransferred; //if (n >= e.Buffer.Length || ProtocolType == ProtocolType.Tcp && n >= 1460 || ProtocolType == ProtocolType.Udp && n >= 1464) //{ // WriteLog("接收的实际数据大小{0}超过了缓冲区大小,需要根据真实MTU调整缓冲区大小以提高效率!", n); //} }
/// <summary> /// 开始异步接收数据 /// </summary> /// <param name="e"></param> protected virtual void ReceiveAsync(NetEventArgs e) { if (!Client.IsBound) Bind(); // 如果没有传入网络事件参数,从对象池借用 if (e == null) e = Pop(); if (!Client.ReceiveAsync(e)) RaiseCompleteAsync(e); }
/// <summary>开始异步接收,同时处理传入的事件参数,里面可能有接收到的数据</summary> /// <param name="e"></param> internal void Start(NetEventArgs e) { if (_hasStarted) return; _hasStarted = true; if (e.BytesTransferred > 0) ProcessReceive(e); ReceiveAsync(); }
/// <summary>处理接收到的数据</summary> /// <param name="e"></param> internal protected virtual void ProcessReceive(NetEventArgs e) { // 统计接收数 IncCounter(); CheckBufferSize(e); if (Received != null) { Received(this, e); } }
/// <summary>错误发生时。负责调用Error事件以及回收网络事件参数</summary> /// <remarks>OnError除了会调用ProcessError外,还会关闭Socket</remarks> /// <param name="e"></param> /// <param name="ex"></param> protected virtual void OnError(NetEventArgs e, Exception ex) { try { ProcessError(e, ex); } finally { Close(); } }
/// <summary>实例化</summary> public SocketBase() { // 子类可能重载协议类型 LocalUri.ProtocolType = ProtocolType; //RemoteUri.ProtocolType = ProtocolType; _arg = NetEventArgs.Pop(); _arg.Completed += (s, e) => RaiseComplete(e as NetEventArgs); SetShowEventLog(); }
/// <summary> /// 接收数据。已重载。接收到0字节表示连接断开! /// </summary> /// <param name="e"></param> protected override void OnReceive(NetEventArgs e) { if (e.BytesTransferred > 0) base.OnReceive(e); else { //// 关闭前回收 //Push(e); //Close(); OnError(e, null); } }
/// <summary> /// 异步接收 /// </summary> /// <param name="e"></param> protected override void ReceiveAsync(NetEventArgs e) { if (!Client.IsBound) Bind(); // 如果没有传入网络事件参数,从对象池借用 if (e == null) e = Pop(); //e.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); // 兼容IPV6 IPAddress address = AddressFamily == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Any : IPAddress.Any; e.RemoteEndPoint = new IPEndPoint(address, 0); if (!Client.ReceiveFromAsync(e)) RaiseCompleteAsync(e); }
/// <summary> /// 已重载。 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected override void OnReceived(object sender, NetEventArgs e) { try { if (e.BytesTransferred > 100) WriteLog("Discard {0} [{1}]", e.RemoteEndPoint, e.BytesTransferred); else WriteLog("Discard {0} [{1}] {2}", e.RemoteEndPoint, e.BytesTransferred, e.GetString()); } finally { Disconnect(e.UserToken as SocketBase); } }
/// <summary>错误发生/断开连接时。拦截Error事件中的所有异常,不外抛,防止因为Error异常导致多次调用OnError</summary> /// <param name="e"></param> /// <param name="ex"></param> internal protected void ProcessError(NetEventArgs e, Exception ex) { if (Error != null) { try { Error(this, new ExceptionEventArgs { Exception = ex }); } catch (Exception ex2) { WriteLog(ex2.ToString()); } } }
/// <summary>已重载。</summary> /// <param name="e"></param> protected override void OnComplete(NetEventArgs e) { switch (e.LastOperation) { case SocketAsyncOperation.Receive: case SocketAsyncOperation.ReceiveFrom: case SocketAsyncOperation.ReceiveMessageFrom: OnReceive(e); return; default: break; } base.OnComplete(e); }
/// <summary>已重载。服务器不会因为普通错误而关闭Socket停止服务</summary> /// <param name="e"></param> /// <param name="ex"></param> protected override void OnError(NetEventArgs e, Exception ex) { var isAborted = e.SocketError == SocketError.OperationAborted; try { ProcessError(e, ex); } finally { if (isAborted) { Close(); } } }
/// <summary> /// 已重载。 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected override void OnAccepted(object sender, NetEventArgs e) { try { WriteLog("Daytime {0}", e.RemoteEndPoint); base.OnAccepted(sender, e); Byte[] buffer = Encoding.ASCII.GetBytes(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffffff")); Send(e.UserToken as SocketBase, buffer, 0, buffer.Length, e.RemoteEndPoint); } finally { Disconnect(e.UserToken as SocketBase); } }
/// <summary>接收到数据时</summary> /// <remarks> /// 网络事件参数使用原则: /// 1,得到者负责回收(通过方法参数得到) /// 2,正常执行时自己负责回收,异常时顶级负责回收 /// 3,把回收责任交给别的方法 /// </remarks> /// <param name="e"></param> protected virtual void OnReceive(NetEventArgs e) { // Socket错误由各个处理器来处理 if (e.SocketError != SocketError.Success) { OnError(e, null); return; } // 没有接收事件时,马上开始处理重建委托 if (Received == null) { ReceiveAsync(); return; } Process(e, ReceiveAsync, ProcessReceive); }
/// <summary> /// 已重载。 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected override void OnReceived(object sender, NetEventArgs e) { try { if (e.BytesTransferred > 100) WriteLog("Echo {0} [{1}]", e.RemoteEndPoint, e.BytesTransferred); else WriteLog("Echo {0} [{1}] {2}", e.RemoteEndPoint, e.BytesTransferred, e.GetString()); Send(e.UserToken as SocketBase, e.Buffer, e.Offset, e.BytesTransferred, e.RemoteEndPoint); // 等一秒,等客户端接收数据 Thread.Sleep(1000); } finally { Disconnect(e.UserToken as SocketBase); } }
/// <summary> /// 已重载。 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected override void OnAccepted(object sender, NetEventArgs e) { try { WriteLog("Daytime {0}", e.RemoteEndPoint); base.OnAccepted(sender, e); TimeSpan ts = DateTime.Now - StartTime; Int32 s = (Int32)ts.TotalSeconds; // 因为要发往网络,这里调整网络字节序 s = IPAddress.HostToNetworkOrder(s); Byte[] buffer = BitConverter.GetBytes(s); Send(e.UserToken as SocketBase, buffer, 0, buffer.Length, e.RemoteEndPoint); } finally { Disconnect(e.UserToken as SocketBase); } }
/// <summary>把对象归还到池里</summary> /// <remarks> /// 网络事件参数使用原则: /// 1,得到者负责回收(通过方法参数得到) /// 2,正常执行时自己负责回收,异常时顶级或OnError负责回收 /// 3,把回收责任交给别的方法 /// 4,事件订阅者不允许回收,不允许另作他用 /// </remarks> /// <param name="e"></param> public static void Push(NetEventArgs e) { if (e == null) { return; } e.Error = null; e.UserToken = null; e.Socket = null; e.Session = null; e.AcceptSocket = null; e.RemoteEndPoint = null; // 清空缓冲区,避免事件池里面的对象占用内存 //e.SetBuffer(0); bpool.Push(e); Pool.Push(e); }
/// <summary> /// 开始异步接收数据 /// </summary> /// <param name="e"></param> protected virtual void ReceiveAsync(NetEventArgs e) { if (!Server.IsBound) Bind(); // 如果没有传入网络事件参数,从对象池借用 if (e == null) e = Pop(); //e.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); // 兼容IPV6 IPAddress address = AddressFamily == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Any : IPAddress.Any; e.RemoteEndPoint = new IPEndPoint(address, 0); if (!Server.ReceiveFromAsync(e)) { if (e.BytesTransferred > 0) RaiseCompleteAsync(e); else Push(e); } }
/// <summary> /// 已重载。 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected override void OnReceived(object sender, NetEventArgs e) { if (e.BytesTransferred > 1024) { WriteLog("{0}的数据包大于1k,抛弃!", e.RemoteEndPoint); return; } //WriteLog("{0} {1}", e.RemoteEndPoint, Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred)); WriteLog("{0} [{1}] {2}", e.RemoteEndPoint, e.BytesTransferred, e.GetString()); // 兼容IPV6 IPEndPoint remote = e.RemoteEndPoint as IPEndPoint; if (remote != null && remote.Address != IPAddress.Any && remote.Address != IPAddress.IPv6Any) { UdpServer us = sender as UdpServer; us.Send(e.Buffer, e.Offset, e.BytesTransferred, e.RemoteEndPoint); // 这里发送完成后不需要关闭Socket,因为这是UdpServer的Socket } }
/// <summary> /// 已重载。 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected override void OnAccepted(object sender, NetEventArgs e) { WriteLog("Chargen {0}", e.RemoteEndPoint); //if (ProtocolType == ProtocolType.Tcp) //{ // 使用多线程 Thread thread = new Thread(LoopSend); thread.Name = "Chargen.LoopSend"; thread.IsBackground = true; thread.Priority = ThreadPriority.Lowest; thread.Start(new Object[] { e.UserToken, e.RemoteEndPoint }); //} //else if (ProtocolType == ProtocolType.Udp) //{ // Send(e.UserToken as SocketBase, e.RemoteEndPoint as IPEndPoint); //} // 调用基类,为接收数据准备,避免占用过大内存 base.OnAccepted(sender, e); }
/// <summary> /// 已重载。 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected override void OnReceived(object sender, NetEventArgs e) { TcpClientX tc = sender as TcpClientX; try { if (e.BytesTransferred > 1024) { WriteLog("{0}的数据包大于1k,抛弃!", tc.RemoteEndPoint); } else { WriteLog("{0} [{1}] {2}", tc.RemoteEndPoint, e.BytesTransferred, e.GetString()); if (tc != null && tc.Client.Connected) tc.Send(e.Buffer, e.Offset, e.BytesTransferred); } } finally { tc.Close(); } }
internal void SetRemote(NetEventArgs e) { var ep = e.RemoteEndPoint as IPEndPoint; if ((ep == null || ep.Address.IsAny() && ep.Port == 0) && RemoteEndPoint != null) e.RemoteEndPoint = RemoteEndPoint; }
/// <summary>已重载。设置RemoteEndPoint</summary> /// <param name="e"></param> protected override void OnComplete(NetEventArgs e) { SetRemote(e); base.OnComplete(e); }
/// <summary>接收数据。已重载。接收到0字节表示连接断开!</summary> /// <param name="e"></param> protected override void OnReceive(NetEventArgs e) { if (_Received != null) SetEvent(); //if (e.BytesTransferred > 0 || !DisconnectWhenEmptyData) if (e.BytesTransferred > 0) base.OnReceive(e); else OnError(e, null); }
void TcpClientX_Received(object sender, NetEventArgs e) { if (_Received != null) _Received(this, new ReceivedEventArgs(e.GetStream())); }
/// <summary> /// 已重载。 /// </summary> /// <param name="e"></param> protected override void OnComplete(NetEventArgs e) { switch (e.LastOperation) { case SocketAsyncOperation.Accept: break; case SocketAsyncOperation.Connect: break; case SocketAsyncOperation.Disconnect: break; case SocketAsyncOperation.None: break; case SocketAsyncOperation.Receive: case SocketAsyncOperation.ReceiveFrom: case SocketAsyncOperation.ReceiveMessageFrom: OnReceive(e); return; case SocketAsyncOperation.Send: break; case SocketAsyncOperation.SendPackets: break; case SocketAsyncOperation.SendTo: break; default: break; } base.OnComplete(e); }
/// <summary> /// 处理接收 /// </summary> /// <param name="e"></param> private void ProcessReceive(NetEventArgs e) { if (NoDelay && e.SocketError != SocketError.OperationAborted) ReceiveAsync(); try { // Socket错误由各个处理器来处理 if (e.SocketError != SocketError.Success) { OnError(e, null); // OnError里面已经被回收,赋值为null,否则后面finally里面的Push会出错 e = null; return; } #if DEBUG Int32 n = e.BytesTransferred; if (n >= e.Buffer.Length || ProtocolType == ProtocolType.Tcp && n >= 1452 || ProtocolType == ProtocolType.Udp && n >= 1464) { WriteLog("接收的实际数据大小{0}超过了缓冲区大小,需要根据真实MTU调整缓冲区大小以提高效率!", n); } #endif if (Received != null) Received(this, e); } finally { if (NoDelay) Push(e); else ReceiveAsync(e); } }
void ShowEvent(NetEventArgs e) { //WriteLog("Completed[{4}] {0} {1} {2} [{3}]", this, e.LastOperation, e.SocketError, e.BytesTransferred, e.ID); var sb = new StringBuilder(); sb.AppendFormat("[{0}] {1} {2}://{3}", e.ID, e.LastOperation, ProtocolType, LocalEndPoint); var ep = e.RemoteIPEndPoint; //if (ep == null || ep.Address.IsAny()) ep = RemoteEndPoint; if ((ep == null || ep.Address.IsAny()) && e.LastOperation == SocketAsyncOperation.Accept && e.AcceptSocket != null) ep = e.AcceptSocket.RemoteEndPoint as IPEndPoint; if (ep != null && !ep.Address.IsAny()) sb.AppendFormat("=>{0}", ep); //sb.AppendFormat(" {0}", e.LastOperation); if (e.SocketError != SocketError.Success) sb.AppendFormat(" {0}", e.SocketError); sb.AppendFormat(" [{0}]", e.BytesTransferred); WriteLog(sb.ToString()); }
/// <summary>处理接收到的数据</summary> /// <param name="e"></param> protected internal override void ProcessReceive(NetEventArgs e) { if (e.Session == null) e.Session = CreateSession(); base.ProcessReceive(e); }
/// <summary>处理异步结果。</summary> /// <param name="e">事件参数</param> /// <param name="start">开始新异步操作的委托</param> /// <param name="process">处理结果的委托</param> protected virtual void Process(NetEventArgs e, Func start, Action<NetEventArgs> process) { // Socket错误由各个处理器来处理 if (e.SocketError != SocketError.Success) { OnError(e, null); return; } try { // 业务处理的任何异常,都将引发Error事件,但不会影响重新建立新的异步操作 process(e); } catch (Exception ex) { try { OnError(e, ex); } catch { } return; } // 如果不是操作取消,在处理业务完成后再开始异步操作 if (!Disposed) start(); }
/// <summary>完成事件分发中心。 /// 正常执行时OnComplete必须保证回收参数e,异常时RaiseComplete将能够代为回收 /// </summary> /// <param name="e"></param> protected virtual void OnComplete(NetEventArgs e) { }
/// <summary> /// 接收到数据时 /// </summary> /// <param name="e"></param> protected virtual void OnReceive(NetEventArgs e) { // Socket错误由各个处理器来处理 if (e.SocketError == SocketError.OperationAborted) { OnError(e, null); return; } // 没有接收事件时,马上开始处理重建委托 if (Received == null) { ReceiveAsync(e); return; } //ProcessReceive(e); // 这里可以改造为使用多线程处理事件 ThreadPoolCallback(ProcessReceive, e); }
static void server_Accepted(object sender, NetEventArgs e) { TcpSession session = e.UserToken as TcpSession; if (session == null) return; //if (e.AcceptSocket != null) // Console.WriteLine("{1} 新连接 {0}", e.AcceptSocket.RemoteEndPoint, session.ID); //else if (e.AcceptSocket == null) Console.WriteLine("奇怪"); //SetEvent(session, true); //XTrace.WriteLine(e.GetString()); //session.Send("欢迎!"); session.Send(e.GetString()); session.Push(e); session.Close(); }