Socket的ReceiveAsync和SendAsync变成Task<int>

在无阻塞环境,Socket的SendAsync和ReceiveAsync显得特别另类。他们返回的不是Task而是bool 值。为了与开发环境兼容【其实就是为了使用ContinueWith】,需要将他们封装,返回为Task<int>.

以下为转换函数:

public class SocketTokenInfo
    {
        public static int SocketMaxWaitTime = 1000 * 60;//Socket一次发送,接收最大的等待时间。单位:毫秒

        ByteBuffer Buffer;

        System.Net.Sockets.Socket Socket;
        System.Net.Sockets.SocketAsyncEventArgs Event;
        System.Threading.CancellationTokenSource Cancel;
        Exception Error;

        Task<int> returnTask;
        int returnValue = -1;//GetData时,是接收到的数据长度. GetHttpHead时,是httpheader的结束位置.
        int ReceivedBytes()
        {
            if (Error != null)
                throw Error;
            return returnValue;
        }

        void CheckCall()
        {
            if (Buffer != null)
                throw new Exception("ReCall Socket Function when Task not end.");
        }

        void EndTaskCall()
        {
            try
            {
                //Cancel.Dispose();
                Event.Dispose();
            }
            catch { }

            Task tmp = returnTask;
            Event.UserToken = null;
            Event = null;
            //Cancel = null;
            returnTask = null;
            HelperExtend.socketToken.Ended(this);

            tmp.Start();
        }


        Task<int> CreatTask()
        {
            if (Cancel == null)
            {
                Cancel = new System.Threading.CancellationTokenSource();
            }
            returnValue = 0;
            Error = null;
            Cancel.CancelAfter(SocketMaxWaitTime);
            returnTask = new Task<int>(ReceivedBytes, Cancel.Token);
            return returnTask;
        }

        #region 发送数据

        public Task<int> SendData(System.Net.Sockets.Socket s, ByteBuffer buf, System.Net.Sockets.SocketAsyncEventArgs e = null)
        {
            CheckCall();

            if (e == null)
                e = new System.Net.Sockets.SocketAsyncEventArgs();
            Event = e;
            e.UserToken = this;

            this.Buffer = buf;
            Buffer.SocketSendEvent(Event);
            this.Socket = s;

            Event.Completed += CheckSend;
            if (!s.SendAsync(Event))
            {
                CheckSend(s, Event);
            }

            return CreatTask();
        }

        void CheckSend(object sender, System.Net.Sockets.SocketAsyncEventArgs Event)
        {
            Event.Completed -= CheckSend;
            returnValue = Event.BytesTransferred;
            this.Buffer.Readed(returnValue);
            EndTaskCall();
        }

        #endregion

        #region HttpHead
        public Task<int> GetHttpHead(System.Net.Sockets.Socket s, ByteBuffer buf, System.Net.Sockets.SocketAsyncEventArgs e=null)
        {
            CheckCall();

            if (e == null)
                e = new System.Net.Sockets.SocketAsyncEventArgs();
            Event = e;
            Event.UserToken = this;

            this.Buffer = buf;
            this.Buffer.SocketReceiveEvent(Event);
            Socket = s;
            

            Event.Completed += CheckHttp;
            if (!s.ReceiveAsync(Event))
            {
                CheckHttp(s, Event);
            }

            return CreatTask();
        }

        void CheckHttp(object sender, System.Net.Sockets.SocketAsyncEventArgs e)
        {
            if (e.BytesTransferred <= 0)
            {//连接已断开.
                Event.Completed -= CheckHttp;
                this.Error = new Exception("Socket is disconnted before headers are received");

                this.EndTaskCall();
                return;
            }
            
            int oldLen = this.Buffer.Count;//上次检查结束位置.
            this.Buffer.Writed(e.BytesTransferred);

            int rtVlue = this.Buffer.LineDoubleCheckASC2(oldLen);//检查\r\n\r\n
            if (rtVlue < 0)
            {//未完成,继续接收数据.
                if (!this.Socket.ReceiveAsync(Event))
                {
                    CheckHttp(this.Socket, Event);
                }
            }
            else
            {//完成httpHeader的接收
                returnValue = rtVlue;
                EndTaskCall();
            }
        }
        #endregion

        #region GetOnce
        //执行一次socket取数据操作.无论是否成功.
        public Task<int> GetOnce(System.Net.Sockets.Socket s,ByteBuffer buf, System.Net.Sockets.SocketAsyncEventArgs e=null)
        {
            CheckCall();

            if (e == null)
                e = new System.Net.Sockets.SocketAsyncEventArgs();
            Event = e;
            e.UserToken = this;

            this.Buffer = buf;
            this.Buffer.SocketReceiveEvent(Event);
            Socket = s;

            Event.Completed += CheckReceiveRst;
            if (!s.ReceiveAsync(Event))
            {
                CheckReceiveRst(s, Event);
            }

            return CreatTask();
        }

        void CheckReceiveRst(object sender, System.Net.Sockets.SocketAsyncEventArgs e)
        {
            Event.Completed -= CheckReceiveRst;
            returnValue = Event.BytesTransferred;
            this.Buffer.Writed(Event.BytesTransferred);

            EndTaskCall();
        }
        #endregion


        #region GetFixLen
        //执行一次socket取数据操作.无论是否成功.
        public Task<int> GetFixLength(System.Net.Sockets.Socket s,int ask,ByteBuffer buf, System.Net.Sockets.SocketAsyncEventArgs e = null)
        {
            CheckCall();

            if (e == null)
                e = new System.Net.Sockets.SocketAsyncEventArgs();
            Event = e;
            e.UserToken = this;

            this.Buffer = buf;
            this.Buffer.SocketReceiveEvent(Event);
            Socket = s;

            returnValue = ask;

            Event.Completed += CheckAskLen;
            if (!s.ReceiveAsync(Event))
            {
                CheckAskLen(s, Event);
            }

            return CreatTask();
        }

        void CheckAskLen(object sender, System.Net.Sockets.SocketAsyncEventArgs Event)
        {
            if(Event.BytesTransferred <= 0)
            {
                Event.Completed -= CheckAskLen;
                this.Error = new Exception("Socket Closed Before Data All");
                EndTaskCall();
                return;
            }

            this.Buffer.Writed(Event.BytesTransferred);
            if(this.Buffer.Count >= returnValue)
            {
                Event.Completed -= CheckAskLen;
                EndTaskCall();
                return;
            }

            if (!this.Socket.ReceiveAsync(Event))
            {
                CheckAskLen(this.Socket, Event);
            }
        }
        #endregion

        #region All
        //接收数据,等待对方断开连接后返回.
        public Task<int> GetAllAndClose(System.Net.Sockets.Socket s, System.Net.Sockets.SocketAsyncEventArgs e, ByteBuffer buf)
        {

            CheckCall();

            if (e == null)
                e = new System.Net.Sockets.SocketAsyncEventArgs();
            Event = e;
            Event.UserToken = this;

            this.Buffer = buf;
            this.Buffer.SocketReceiveEvent(Event);
            Socket = s;


            Event.Completed += CheckAll;
            if (!s.ReceiveAsync(Event))
            {
                CheckAll(s, Event);
            }

            return CreatTask();
        }

        void CheckAll(object sender, System.Net.Sockets.SocketAsyncEventArgs e)
        {
            if (Event.BytesTransferred <= 0)
            {
                Event.Completed -= CheckAll;
                this.Socket.Shutdown(System.Net.Sockets.SocketShutdown.Both);
                this.Socket.Dispose();
                return;
            }
            else
            {
                this.Buffer.Writed(Event.BytesTransferred);
                if (!this.Socket.ReceiveAsync(Event))
                {
                    CheckAll(Socket, Event);
                }
            }
        }
        #endregion
        
        public void DoCancel()
        {
            Cancel.Cancel();
        }
    }

ByteBuffer 是一个缓冲区管理函数.

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值