Windows Phone学习笔记(8) — — UDP套接字

  上一篇写了如何进行TCP通信的套接字,这次来说一些怎么进行UDP的套接字通信,还用之前TCP套接字通信的那个示例页面,只是把后台的TCP通信改为UDP通信。首先我们先来修改SocketClient类

View Code
    public class SocketClient
    {
        Socket _socket = null;
        static ManualResetEvent _clientDone = new ManualResetEvent(false);
        const int TIMEOUT_MILLISECONDS = 5000;
        const int MAX_BUFFER_SIZE = 2048;

        /// <summary>
        /// SocketClient构造函数
        /// </summary>
        public SocketClient()
        {
            //创建一个具有一些属性的套接字
            // AddressFamily.InterNetwork - 该套接字将使用IP版本4寻址方案来解决一个地址
            // SocketType.Dgram - 一个套接字,支持数据(消息)包
            // PrototcolType.Udp - 用户的数据协议(UDP)
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        }

        /// <summary>
        /// 使用已经建立的连接发送数据
        /// </summary>
        /// <param name="serverName">服务器名称</param>
        /// <param name="portNumber">数据发送到的端口号</param>
        /// <param name="data">发送到服务器的数据</param>
        /// <returns>发送请求的结果</returns>
        public string Send(string serverName, int portNumber, string data)
        {
            string response = "Operation Timeout";

            //我们用_socket对象初始化的连接方法
            if (_socket != null)
            {
                // 创建一个SocketAsyncEventArgs对象
                SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();

                //设置SocketAsyncEventArgs对象上下文的属性
                socketEventArg.RemoteEndPoint = new DnsEndPoint(serverName, portNumber);

                // 内联事件处理程序完成事件。
                // Note: This event handler was implemented inline in order to make this method self-contained.
                socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
                {
                    response = e.SocketError.ToString();

                    //开启UI线程
                    _clientDone.Set();
                });

                //添加数据到缓冲数据 Add the data to be sent into the buffer
                byte[] payload = Encoding.UTF8.GetBytes(data);
                socketEventArg.SetBuffer(payload, 0, payload.Length);

                // Sets the state of the event to nonsignaled, causing threads to block
                //设置事件的接收状态,阻塞UI线程
                _clientDone.Reset();

                // Make an asynchronous Send request over the socket
                //让异步套接字发送请求
                _socket.SendToAsync(socketEventArg);

                //这对时间内如果没有反应的话,阻塞UI线程最大时间为TIMEOUT_MILLISECONDS设定的毫秒数
                _clientDone.WaitOne(TIMEOUT_MILLISECONDS);
            }
            else
            {
                response = "Socket is not initialized";
            }

            return response;
        }


        /// <summary>
        /// Receive data from the server
        /// </summary>
        /// <param name="portNumber">The port on which to receive data</param>
        /// <returns>The data received from the server</returns>
        public string Receive(int portNumber)
        {
            string response = "Operation Timeout";

            //我们正在建立一个套接字接收
            if (_socket != null)
            {
                // 创建一个SocketAsyncEventArgs对象
                SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
                socketEventArg.RemoteEndPoint = new IPEndPoint(IPAddress.Any, portNumber);

                // 设置缓冲区接收数据
                socketEventArg.SetBuffer(new Byte[MAX_BUFFER_SIZE], 0, MAX_BUFFER_SIZE);

                //内联事件处理程序完成事件。
                // Note: This even handler was implemented inline in order to make this method self-contained.
                socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
                {
                    if (e.SocketError == SocketError.Success)
                    {
                        //从缓冲区检索数据
                        response = Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred);
                        response = response.Trim('\0');
                    }
                    else
                    {
                        response = e.SocketError.ToString();
                    }

                    _clientDone.Set();
                });

                _clientDone.Reset();
                _socket.ReceiveFromAsync(socketEventArg);
                _clientDone.WaitOne(TIMEOUT_MILLISECONDS);
            }
            else
            {
                response = "Socket is not initialized";
            }
            return response;
        }

        /// <summary>
        /// 关闭套接字连接并且释放所有相关资源
        /// </summary>
        public void Close()
        {
            if (_socket != null)
            {
                _socket.Close();
            }
        }
    }

对比可以看到,在UDP通信中SocketClient中之后Send和Receive两个方法,这是因为UDP不需要先进行与服务器的连接。在改好SocketClient类之后,我们来修改下页面中的两个单机事件btnEcho_Click和btnGetQuote_Click,其它方法保留

View Code
        private void btnEcho_Click(object sender, RoutedEventArgs e)
        {
            //清空日志
            ClearLog();

            // Make sure we can perform this action with valid data
            //确保我们可以执行这个动作与数据的有效
            if (ValidateRemoteHost() && ValidateInput())
            {
                //实例化SocketClient
                SocketClient client = new SocketClient();

                // Attempt to send our message to be echoed to the echo server
                //尝试发送消息响应服务器
                Log(String.Format("Sending '{0}' to server ...", txtInput.Text), true);
                string result = client.Send(txtRemoteHost.Text, ECHO_PORT, txtInput.Text);
                Log(result, false);

                //接收来自服务器的响应
                Log("Requesting Receive ...", true);
                result = client.Receive(ECHO_PORT);
                Log(result, false);

                //关闭套接字的连接
                client.Close();
            }
        }

        private void btnGetQuote_Click(object sender, RoutedEventArgs e)
        {
            // Clear the log 
            ClearLog();

            // Make sure we can perform this action with valid data
            if (ValidateRemoteHost())
            {
                SocketClient client = new SocketClient();

                Log(String.Format("Requesting a quote from server '{0}' ...", txtRemoteHost.Text), true);
                string dummyMessage = " ";
                string result = client.Send(txtRemoteHost.Text, QOTD_PORT, dummyMessage);
                Log(result, false);

                // Receive response from the QOTD server
                Log("Requesting Receive ...", true);
                result = client.Receive(QOTD_PORT);
                Log(result, false);

                // Close the socket connection explicitly
                client.Close();
            }
        }

下面是触发btnEcho_Click和btnGetQuote_Click事件以后的截图

  

posted on 2012-11-24 20:39  松竹柏柳  阅读(396)  评论(0编辑  收藏  举报

导航