/// <summary> /// 开始接收数据 /// </summary> private void StartReceive() { if (!_state) { return; } try { IFixedCacheStub <SocketBuffStub> stub = ChannelConst.BuffAsyncStubPool.Rent(); if (stub == null) { throw new System.Exception("#Cannot rent an async recv io-stub for socket recv async action."); } SocketAsyncEventArgs e = stub.Cache.Target; //set callback var = receiver stub.Tag = this; e.AcceptSocket = _socket; e.UserToken = stub; bool result = e.AcceptSocket.ReceiveAsync(e); //Sync process data. if (!result) { ProcessReceive(stub); } } catch (System.Exception ex) { _tracing.Error(ex, null); Stop(); } }
/// <summary> /// 处理接收的数据 /// </summary> /// <param name="stub">带缓冲区的固定缓存存根</param> internal void ProcessReceive(IFixedCacheStub <SocketBuffStub> stub) { if (stub.Cache.Target.BytesTransferred > 0 && stub.Cache.Target.SocketError == SocketError.Success) { //接收成功 try { ProcessData(stub, stub.Cache.Target.BytesTransferred); } catch (System.Exception ex) { _tracing.Error(ex, null); } finally { StartReceive(); } } else { //giveback current rented BuffSocketStub. ChannelConst.BuffAsyncStubPool.Giveback(stub); Stop(); } }
/// <summary> /// 归还一个缓存 /// </summary> /// <param name="cache">缓存</param> /// <exception cref="Exception">归还缓存失败,因为目标缓存容器已经满了</exception> public void Giveback(IFixedCacheStub <T> cache) { if (cache == null) { throw new ArgumentNullException(nameof(cache)); } lock (_lockObj) { if (Interlocked.Read(ref _remainingCount) >= _capacity) { throw new Exception("Can not giveback a cache, because target caches count has been full."); } cache.Cache.Clear(); cache.Tag = null; _caches.Push((ICacheStub <T>)cache); Interlocked.Increment(ref _remainingCount); } }
/// <summary> /// 发送数据 /// <para>* 如果此方法进行发送的元数据,可能是自动分包后的数据。</para> /// </summary> /// <param name="data">要发送的数据</param> /// <returns>返回发送的字节数</returns> protected override int InnerSend(byte[] data) { int sendCount = 1; try { if (_socket == null || !_socket.Connected) { return(-1); } if (data.Length > ChannelConst.MaxMessageDataLength) { _tracing.Warn(string.Format("#Illegal data size: {0}, current allow size: {1}", data.Length, ChannelConst.MaxMessageDataLength)); return(-1); } //get fixed cache. IFixedCacheStub <NoBuffSocketStub> stub = ChannelConst.NoBuffAsyncStubPool.Rent(); if (stub == null) { _tracing.Warn("Cannot rent a socket async event args cache."); return(-2); } stub.Tag = this; SocketAsyncEventArgs args = stub.Cache.Target; args.SetBuffer(data, 0, data.Length); args.UserToken = stub; bool result = _socket.SendAsync(args); //同步发送完成 if (!result) { //注意,在这里如果是同步完成的,根据MSDN的解释,将不会触发Completed事件 sendCount = args.BytesTransferred; ChannelConst.NoBuffAsyncStubPool.Giveback(stub); } return(sendCount); } catch (System.Exception ex) { _tracing.Error(ex, null); return(sendCount); } }
/// <summary> /// Socket接收到内存片段的事件 /// </summary> /// <param name="stub">带缓冲区的固定缓存存根</param> /// <param name="bytesTransferred">接收到的数据长度</param> public SocketSegmentReceiveEventArgs(IFixedCacheStub <SocketBuffStub> stub, int bytesTransferred) : base(bytesTransferred) { Stub = stub; }
/// <summary> /// 命名管道接收到内存片段的事件 /// </summary> /// <param name="bytesTransferred">接收到的数据长度</param> public NamedPipeSegmentReceiveEventArgs(IFixedCacheStub <BuffStub> stub, int bytesTransferred) : base(bytesTransferred) { Stub = stub; }
/// <summary> /// 处理数据 /// </summary> /// <param name="stub">带缓冲区的固定缓存存根</param> /// <param name="bytesTransferred">接收到的数据长度</param> private void ProcessData(IFixedCacheStub <SocketBuffStub> stub, int bytesTransferred) { ReceivedDataHandler(new SocketSegmentReceiveEventArgs(stub, bytesTransferred)); }