Silverlight Socket通信

 public delegate void ConnectEventHandler();//定义连接委托
    public delegate void SendEventHandler();//定义发送委托
    public delegate void PackageEventHandler();//定义收到一个完整的数据包委托

    public class SocketHelper
    {
        private Socket socket;//定义Socket
        private SocketAsyncEventArgs socketArgs;//定义Socket参数
        public event ConnectEventHandler ConnectCompleted;//定义连接成功后触发的事件
        public event SendEventHandler SendCompleted;//定义发送成功后触发的事件
        public event PackageEventHandler PackageCompleted;//定义收到一个完整的数据包后触发的事件

        private byte[] tempBuffer = new byte[1024];//临时缓冲区,只存放不完整的包
        private List<byte[]> packageList = new List<byte[]>();//存放完整的包的集合
        private int packLen = 0;//当前包的长度
        private int packLenLeft = 0;//当前包还需要多少字节
        private bool state = true;//当前是准备接收新包还是旧包,true表示接收新包。

        //如果socket发送成功,则返回true
        private bool isSend = true;
        public bool IsSend
        {
            get { return isSend; }
        }

        /// <summary>
        /// 构造函数,初始化socket,设置相关属性和参数
        /// </summary>
        public SocketHelper()
        {
            socket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            socketArgs = new SocketAsyncEventArgs();
        }

        /// <summary>
        /// 连接服务器
        /// </summary>
        /// <param name="ipAddress">服务器IP地址</param>
        /// <param name="port">端口号</param>
        public void Connect(string ipAddress, int port)
        {
            //设置到远程终节点属性
            socketArgs.RemoteEndPoint = new DnsEndPoint(ipAddress, port);

            //设置好当Socket任何一个动作完成时的回调函数。
            socketArgs.Completed += new EventHandler<SocketAsyncEventArgs>(socketArgs_Completed);

            //执行异步连接。
            socket.ConnectAsync(socketArgs);
        }

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="content">消息内容</param>
        public bool Send(string content)
        {
            //默认连接存在
            bool isConnect = true;

            if (socket != null && socket.Connected)
            {
                if (!string.IsNullOrEmpty(content.Trim()))
                {
                    //将传入的字符串转换的Byte字节数组
                    byte[] bytes = Encoding.UTF8.GetBytes(content);

                    //新实例化一个Socket参数
                    socketArgs = new SocketAsyncEventArgs();

                    //设置Socket参数的缓冲区参数,将我们的字节数组设置为Socket的缓冲区。
                    socketArgs.SetBuffer(bytes, 0, bytes.Length);

                    //发送数据
                    try
                    {
                        socket.SendAsync(socketArgs);
                    }
                    catch
                    {
                        isSend = false;
                    }
                    finally
                    {
                        //触发客户端事件
                        if (SendCompleted != null)
                        {
                            SendCompleted();
                        }
                    }
                }
            }
            else
            {
                isConnect = false;
            }

            return isConnect;
        }

        /// <summary>
        /// 关闭连接
        /// </summary>
        public void Close()
        {
            socket.Close();
        }

        /// <summary>
        /// 获取单个包
        /// </summary>
        /// <returns>单个包或null</returns>
        public byte[] GetPackage()
        {
            if (packageList.Count > 0)
            {
                byte[] SingleByte = packageList[0];

                packageList.RemoveAt(0);

                return SingleByte;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 任何一个Socket动作完成,都回调该函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void socketArgs_Completed(object sender, SocketAsyncEventArgs e)
        {
            switch (e.LastOperation)
            {
                case SocketAsyncOperation.Connect:
                    ProcessConnect(e);
                    break;
                //case SocketAsyncOperation.Send:
                //    ProcessSend(e);
                //    break;
                case SocketAsyncOperation.Receive:
                    ProcessReceive(e);
                    break;
            }
        }

        /// <summary>
        /// 连接成功后,触发的客户端事件
        /// </summary>
        private void ProcessConnect(SocketAsyncEventArgs e)
        {
            //连接成功后,就进入准备接收状态
            ProcessSend(e);

            //触发客户端事件
            if (ConnectCompleted != null)
            {
                ConnectCompleted();
            }
        }

        /// <summary>
        /// 执行等待接收服务器发回的数据(不管有没有发送操作)
        /// </summary>
        private void ProcessSend(SocketAsyncEventArgs e)
        {
            //定义个空的字节数组,设置好其大小
            byte[] bytes = new byte[1024];

            //将前面定义字节数组设置成缓冲区
            e.SetBuffer(bytes, 0, bytes.Length);

            //执行异步接收
            socket.ReceiveAsync(e);
        }

        /// <summary>
        /// 接收完成后,处理数据
        /// </summary>
        /// <param name="e"></param>
        private void ProcessReceive(SocketAsyncEventArgs e)
        {
            if (socket.Connected)
            {
                //在执行好接收后,本地SOCKET的缓冲区就会被服务器发送的数据填充。
                //将收到的零散数据放到临时缓冲区中

                //创建一个新数组,存放传来的数据
                byte[] realByte = new byte[e.BytesTransferred];

                //去buffer中前N位有效数据
                Array.Copy(e.Buffer, 0, realByte, 0, e.BytesTransferred);

                //处理数据
                DisposeByte(realByte);

                //将socket一直处于接收状态
                socket.ReceiveAsync(e);
            }
        }

        /// <summary>
        /// 返回实际的字节数组
        /// </summary>
        /// <param name="arrByte">目标数组</param>
        /// <returns>实际数组</returns>
        private byte[] GetRealByte(byte[] arrByte)
        {
            int tag = arrByte.Length;

            for (int i = arrByte.Length - 1; i >= 0; i--)
            {
                if (arrByte[i].ToString() != "0")
                {
                    break;
                }

                tag--;
            }

            byte[] realByte = new byte[tag];

            Array.Copy(arrByte, 0, realByte, 0, tag);

            return realByte;
        }

        /// <summary>
        /// 处理从服务器端发来的数据,对包进行分析
        /// </summary>
        /// <param name="arrByte">服务器端发来的数据</param>
        private void DisposeByte(byte[] arrByte)
        {
            byte[] realByte = GetRealByte(arrByte);//获得实际的字节数组
            int recLen = realByte.Length;//收到的包还剩下多少
            int sepIndex = -1;//分隔符所在的位置

            while (recLen > 0)
            {
                if (state)
                {
                    //准备接收新包

                    //获取第一个分隔符所在的位置
                    for (int i = 0; i < realByte.Length; i++)
                    {
                        if (realByte[i].ToString() == "31")
                        {
                            sepIndex = i;
                            break;
                        }
                    }

                    if (sepIndex >= 0)
                    {
                        //找到分隔符

                        string strLen = "";

                        int buffIndex = GetRealByte(tempBuffer).Length;//查看缓冲区索引的位置

                        if (buffIndex == 0)
                        {
                            for (int j = 0; j < sepIndex; j++)
                            {
                                strLen += Encoding.UTF8.GetString(realByte, j, 1);
                            }
                            packLen = Convert.ToInt32(strLen);
                            packLenLeft = packLen;
                            recLen = recLen - sepIndex - 1;
                            state = false;
                        }
                        else
                        {
                            for (int k = 0; k < buffIndex; k++)
                            {
                                strLen += Encoding.UTF8.GetString(tempBuffer, k, 1);
                            }
                            for (int l = 0; l < sepIndex; l++)
                            {
                                strLen += Encoding.UTF8.GetString(realByte, l, 1);
                            }
                            packLen = Convert.ToInt32(strLen);
                            packLenLeft = packLen;
                            recLen = recLen - sepIndex - 1;
                            state = false;
                        }
                    }
                    else
                    {
                        //没找到分隔符

                        int buffIndex = GetRealByte(tempBuffer).Length;//查看缓冲区索引的位置

                        //将剩下的包放到缓冲区中
                        Array.Copy(realByte, 0, tempBuffer, buffIndex, realByte.Length);

                        recLen = 0;

                        //更改状态
                        state = true;
                    }
                }
                else
                {
                    //准备接收旧包

                    if (packLenLeft <= recLen)
                    {
                        //需要的长度小于等于字节数组剩下的长度,因此可以取得完整包

                        int buffIndex = GetRealByte(tempBuffer).Length;//查看缓冲区索引的位置,如果为0,则表示缓冲区为空

                        if (buffIndex == 0)
                        {
                            //将完整的包放到集合中
                            byte[] tempByte1 = new byte[packLen];
                            Array.Copy(realByte, sepIndex + 1, tempByte1, 0, packLen);
                            packageList.Add(tempByte1);

                            //计算收到的包还剩下多少
                            recLen = recLen - packLen;

                            //生成新的realByte
                            byte[] tempByte2 = new byte[recLen];
                            Array.Copy(realByte, sepIndex + packLen + 1, tempByte2, 0, recLen);
                            realByte = new byte[recLen];
                            Array.Copy(tempByte2, 0, realByte, 0, tempByte2.Length);

                            //更改状态
                            state = true;
                        }
                        else
                        {
                            if (sepIndex == -1)
                            {
                                Array.Copy(realByte, 0, tempBuffer, buffIndex, packLenLeft);
                            }
                            else
                            {
                                Array.Copy(realByte, 0, tempBuffer, buffIndex, packLenLeft + sepIndex + 1);
                            }

                            int index = 0;

                            //获取tempBuffer中第一个分隔符所在的位置
                            for (int i = 0; i < tempBuffer.Length; i++)
                            {
                                if (tempBuffer[i].ToString() == "31")
                                {
                                    index = i;
                                    break;
                                }
                            }

                            byte[] tempByte3 = new byte[packLen];
                            Array.Copy(tempBuffer, index + 1, tempByte3, 0, packLen);
                            packageList.Add(tempByte3);

                            recLen = recLen - packLenLeft;

                            byte[] tempByte4 = new byte[recLen];
                            Array.Copy(realByte, packLenLeft, tempByte4, 0, recLen);

                            realByte = new byte[recLen];
                            Array.Copy(tempByte4, 0, realByte, 0, tempByte4.Length);

                            tempBuffer = new byte[1024];

                            //更改状态
                            state = true;
                        }

                        //触发客户端事件
                        if (PackageCompleted != null)
                        {
                            PackageCompleted();
                        }
                    }
                    else
                    {
                        //剩下的小于我们需要的长度,不能取得完整包

                        //缓冲
                        int tempIndex = GetRealByte(tempBuffer).Length;

                        //将剩下的包放到缓冲区中
                        //Array.Copy(realByte, sepIndex + 1, tempBuffer, tempIndex, recLen);
                        //Array.Copy(realByte, 0, tempBuffer, tempIndex, recLen);
                        Array.Copy(realByte, 0, tempBuffer, tempIndex, realByte.Length);

                        packLenLeft = packLenLeft - recLen;
                        recLen = 0;

                        //更改状态
                        state = false;
                    }
                }
            }
        }
    }

http://www.codeproject.com/Articles/31018/Synchronous-Web-Service-Calls-with-Silverlight-Dis

posted @ 2012-02-13 14:54  Kingdom_0  阅读(336)  评论(0编辑  收藏  举报