当前位置:编程学习 > C#/ASP.NET >>

让人头疼的Socket断开Disconnect方法,前面是基于SocketAsyncEventArgs的操作。

--------------------编程问答-------------------- 代码还没完,继续贴代码。

        /// <summary>
        /// 发送数据,将来源数据发送到已连接的服务端
        /// </summary>
        /// <param name="sendBytes">要发送的数据</param>
        public void Send(byte[] sendBytes)
        {
            if (!m_bIsConnect)
                throw new Exception("Don't Connected");
            if (!m_socket.Connected)
                throw new Exception("Don't Connected");
            if(m_writeEventArg.Buffer == null)
                throw new ArgumentNullException("buffer","缓冲区尚未设置");
            if (sendBytes.Length > m_writeEventArg.Count)
                throw new ArgumentOutOfRangeException("sendBytes", "发送字节数超出缓冲区");
            for (int i = 0; i < sendBytes.Length; i++)
            {
                m_writeEventArg.Buffer[i + m_writeEventArg.Offset] = sendBytes[i];
            }
            m_writeEventArg.SendPacketsSendSize = sendBytes.Length;
            bool willRaiseEvent = m_socket.SendAsync(m_writeEventArg);
            if (!willRaiseEvent)
            {
                ProcessSend(m_writeEventArg);
            }
        }

        private void ProcessSend(SocketAsyncEventArgs m_writeEventArg)
        {
            // throw new NotImplementedException();
            // 如果发送失败,报到断开连接
            if (m_writeEventArg.SocketError != SocketError.Success)
            {
                Disconnect();
            }
        }

        public event ConnectionEventHandler Received;
        public event ConnectionEventHandler Connected;
        public event ConnectionEventHandler Disconnected;
        public event ConnectionEventHandler OutPutString;

        /// <summary>
        /// 触发接收事件,实际上参数是SocketAsyncEventArgs,包含了所有的数据和节点信息
        /// </summary>
        /// <param name="e"></param>
        protected void OnReceive(EventArgs e)
        {
            if (Received != null)
            {
                SocketAsyncEventArgs saea = e as SocketAsyncEventArgs;

                string text = "";
                if (saea.RemoteEndPoint != null)
                {
                    text = ((IPEndPoint)saea.RemoteEndPoint).Address.ToString() + ":"
                        + ((IPEndPoint)saea.RemoteEndPoint).Port.ToString();
                }
                byte[] recvBytes = new byte[saea.BytesTransferred];
                for (int i = 0; i < recvBytes.Length; i++)
                {
                    recvBytes[i] = saea.Buffer[i + saea.Offset];
                }
                Received(this, new ConnectionEventArgs(text, this.m_key.ToString(), recvBytes));
            }
        }

        /// <summary>
        /// 触发连接完成事件,该事件包含连接的远程地址和为本地分配的Key
        /// </summary>
        /// <param name="e">来自ProcessConnect的参数</param>
        protected void OnConnect(EventArgs e)
        {
            if (Connected != null)
            {
                SocketAsyncEventArgs saEArg = e as SocketAsyncEventArgs;
                string ip = "";
                if (saEArg.RemoteEndPoint != null)
                {
                    ip = ((IPEndPoint)saEArg.RemoteEndPoint).Address.ToString() + ":"
                        + ((IPEndPoint)saEArg.RemoteEndPoint).Port.ToString();
                }

                Connected(this, new ConnectionEventArgs(ip, this.m_key.ToString(), null));
            }
        }

        protected void OnDisconnect(EventArgs e)
        {
            if (Disconnected != null)
                Disconnected(this, e);
        }

        protected void OnOutPutString(EventArgs e)
        {
            if (OutPutString != null)
                OutPutString(this, e);
        }
    }

    public class ConnectionEventArgs : EventArgs
    {
        // 输出字符串
        public string Text { get; private set; }
        // 事件来源者的Key
        public string Key { get; private set; }
        // 事件需要输出的字节
        public byte[] Bytes { get; private set; }

        public ConnectionEventArgs(string text, string key, byte[] bytes)
        {
            Text = text;
            Key = key;
            Bytes = bytes;
        }
    }
--------------------编程问答-------------------- 上面的Send函数中,将

m_writeEventArg.SendPacketsSendSize = sendBytes.Length;

这句改成下面这句。

m_writeEventArg.SetBuffer(m_writeEventArg.Offset, sendBytes.Length); --------------------编程问答-------------------- 附上命令行模式的测试程序代码:

class Program
    {
        static void Main(string[] args)
        {
            new MainClass().Run();
        }
    }

    class MainClass
    {
        ITCPAsyncClient asyncClient;
        public MainClass()
        {
            IPEndPoint ip = new IPEndPoint(IPAddress.Parse("164.70.6.63"),9002);
            asyncClient = new TCPAsyncClient(ip, 1);
            asyncClient.Connected += new ConnectionEventHandler(DoEventThings);
            asyncClient.Received += new ConnectionEventHandler(DoEventThings);
            asyncClient.Disconnected +=new ConnectionEventHandler(DoEventThings);
            asyncClient.OutPutString += new ConnectionEventHandler(DoEventThings);
            byte[] buffer = new byte[1024];
            asyncClient.SetBuffer(buffer, 0, 1024);
        }

        void DoEventThings(object sender, EventArgs e)
        {
            //throw new NotImplementedException();
            string show = "";
            ConnectionEventArgs cnEArg = e as ConnectionEventArgs;
            if (cnEArg.Text != null)
                show += cnEArg.Text + " ";
            if (cnEArg.Key != null)
                show += cnEArg.Key + ":";
            if(cnEArg.Bytes!= null)
                for (int i = 0; i < cnEArg.Bytes.Length; i++)
                {
                    show += cnEArg.Bytes[i].ToString("X2") + " ";
                }
            Console.WriteLine(show);
        }

        public void Run()
        {
            asyncClient.Connect();

            string input = "";
            while (true)
            {
                Console.WriteLine("输入要发送的数据或者输入d回车断开连接");
                input = Console.ReadLine();
                if (input.ToLower() == "d")
                {
                    asyncClient.Disconnect();
                    Console.WriteLine("看到断开提示后,输入c重新连接或者q退出程序");
                    input = Console.ReadLine();
                    if (input.ToLower() == "c")
                    {
                        asyncClient.Connect();
                        continue;
                    }
                    else
                    {
                        break;
                    }
                }
                else
                {
                    if (input.Length == 0)
                        continue;
                    asyncClient.Send(Encoding.Default.GetBytes(input));
                }
            }
        }
    }
--------------------编程问答-------------------- setbuffer的函数实现呢?没有吗? --------------------编程问答-------------------- 在用使用SocketAsyncEventArgs ,关注中! --------------------编程问答-------------------- 重用没有什么必要,百分之九十九点九的开销都用掉了。。不在乎那一点。。
补充:.NET技术 ,  .NET Framework
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,