`
qzriso
  • 浏览: 242915 次
  • 性别: Icon_minigender_1
  • 来自: ph
社区版块
存档分类
最新评论

Silverlight Socket 实现收发信息

阅读更多

刚接触Silverlight的时候,除了其异步应用WCF、流媒体、动画效果等方面外,Socket是最另我兴奋的功能。

在Web上实现Socket虽然不是什么新鲜事了,Activex,flash等都可以实现这样的效果,但是Silverlight这样方便的运用Socket让服务器与客户端通信确是我之前没有体验过的。

用它可以做什么?可以连线式的让服务器与客户端交互,而且,是在Web上,那么Web开发游戏,语音,视频聊天等都可以基于Socket功能实现,另外,服务器端是独立出来的,不依赖IIS进程,这样让数据之间的交互更自由。

废话不说,下面来看看如何实现

首先,在进行数据交换之前,我们必须明白Silverlight Socket的一些规矩和原则。

Silverlight客户端的Socket都是异步的,这点很容易明白,另外就是,考虑到Silverlight是应用到Web上的,而Silverlight的Socket自然就有一些安全限制。

每一个请求到服务器端的新的Socket连接会话Silverlight都会先悄悄的用另一个Socket去请求策略文件,这是很多刚接触Silverlight Socket的人感到郁闷的地方,请求策略时,Silverlight会自己发送一个字符串<policy-file-request/>到服务器的943端口,然后你必须在服务器程序里接收该请求,分析是否是策略请求后,发送一个策略文件的字符串给客户端,客户端接收到策略文件后自己分析完后再发送程序员自己写的数据请求。

客户端的策略请求是自动发送的,策略文件的接收和分析也是自动的,是Silverlight自发工作的,不需要程序员手工写代码进行发送接收和分析。

但是,服务器端接收策略请求需要手工完成,程序员必须创建一个Socket监听943端口(该端口是固定的,客户端策略请求固定发送到该端口),然后分析请求过来的数据是否是策略请求,如果是的,那么就读取策略文件,再将该策略文件发送到客户端就可以了。

另外一个限制,Silverlight Socket 数据交换端口必须在4502-4534范围,也就是说,整个Socket将用到两个端口,一个是943用于策略请求,另一个是4502-4534范围的你指定的数据交换端口。

不管你的Socket代码是如何工作,第一次在连接之前,Silverlight都会发送策略请求,只有成功接收到服务器返回的策略文件后,你的Socket代码才能进行工作,所以在第一次连接的时候,实际上Silverlight是进行了两次Socket,第一次请求策略,成功才进行你的Socket,因此,服务器端必要监听两个端口,但是两个监听可以分开在两个线程上工作(两个线程,不是两个进程)。每个会话请求一次策略后,之后的请求就不会再请求策略了,所以他们不能是线性的工作,而是两个独立的监听,否则会阻塞。

我的服务器端的策略监听和数据监听是用的两个子线程运行,而MS的示例是用的异步方法,都是为了不相互阻塞,用MS的方式也许更有效率些,而我是为了让代码更容易理解。

客户端实现了将文本框的内容发送到服务器端,然后服务器收到后显示出来,然后发回一句字符串,关闭连接,客户端收到服务器端的信息后也关闭连接。就这么简单

好后,具体看看示例,说明很详细。

客户端

建立一个Silverlight项目

XAML

<UserControl x:Class="SilverlightTest.Socket1"

    xmlns="http://schemas.microsoft.com/client/2007"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Width="400" Height="300">

    <Grid x:Name="LayoutRoot" Background="White" ShowGridLines="True">

        <Grid.RowDefinitions >

            <RowDefinition />

            <RowDefinition />

        </Grid.RowDefinitions>

 

        <TextBox x:Name="txtToSend" Grid.Row="0"/>

        <Button Grid.Row="1" Click="OnSend" Content="Send" Margin="20" />

    </Grid>

</UserControl>

代码:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Net;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Animation;

using System.Windows.Shapes;

using System.Net.Sockets;

using System.Threading;

using System.Text;

 

namespace SilverlightTest

{

    public partial class Socket1 : UserControl

    {

        public Socket1()

        {

            InitializeComponent();

        }

 

        //定义一个可在全局使用的Socket

        System.Net.Sockets.Socket socket;

 

        //定义一个同步上下文类,用来将子线程的操作调度到主线程上以可控制UI属性。

        SynchronizationContext syn;

 

        //发送信息按钮的单击事件

        void OnSend(object sender, EventArgs args)

        {

           

            //定义一个字节数组,并将文本框的的类容转换为字节数组后存入

            byte[] bytes = Encoding.UTF8.GetBytes(txtToSend.Text);

           

            //显示信息,可不要。

            txtToSend.Text += "\r\nDnsSafeHost:"+Application.Current.Host.Source.DnsSafeHost;

 

            //将同步上下文设置在当前上下文(线程,主线程,可控制UI的)

            syn = SynchronizationContext.Current;

       

            //socket创建示例,并设置相关属性。

            socket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp);

 

            //定义并实例一个Socket参数

            SocketAsyncEventArgs socketArgs = new SocketAsyncEventArgs();

           

            //设置到远程终节点属性(4502端口,为什么是4502MSSL通信安全上有)

            socketArgs.RemoteEndPoint = new DnsEndPoint(Application.Current.Host.Source.DnsSafeHost, 4502);

 

            //设置好当Socket任何一个动作完成时的回调函数。

            socketArgs.Completed += new EventHandler<SocketAsyncEventArgs>(socketArgs_Completed);

            //Socket参数的用户标识,实际上就是一个可以传递的OBJECT参数。

            socketArgs.UserToken = bytes;

            //执行连接。

            socket.ConnectAsync(socketArgs);

 

           

        }

 

        void socketArgs_Completed(object sender, SocketAsyncEventArgs e)

        {

            //当任何一个Socket动作完成,都回调该函数,然后对LastOperation进行判断后继续执行相应的部分

            switch (e.LastOperation)

            {

                case SocketAsyncOperation.Connect:

                    ProcessConnect(e);

                    break;

                case SocketAsyncOperation.Receive:

                    ProcessReceive(e);

                    break;

                case SocketAsyncOperation.Send:

                    ProcessSend(e);

                    break;

              }

        }

 

        //将数据放入buffer并进行异步发送

        void ProcessConnect(SocketAsyncEventArgs e)

        {

 

            //当连接成功后,获取Socket参数 e传递过来的用户标识(也就是本示例中用户输入的字符串转换的Byte字节数组)

            byte[] bytes = (byte[])e.UserToken;

 

            //设置Socket参数的缓冲区参数,将我们的字节数组设置为Socket的缓冲区。

            e.SetBuffer(bytes, 0, bytes.Length);

           

            //同步一下上下文,显示一下当前的状态信息。

            syn.Post(GetText,"States:"+e.SocketError.ToString()+","+e.LastOperation.ToString());

           

            //发送数据

            socket.SendAsync(e);

           

        }

 

        //发送完成后,执行等待接收服务器发回的数据

        void ProcessSend(SocketAsyncEventArgs e)

        {

            //定义个空的字节数组,设置好其大小

            byte[] bytes = new byte[1024];

            //将前面定义字节数组设置成缓冲区

            e.SetBuffer(bytes, 0, bytes.Length);

            //执行异步接收

            socket.ReceiveAsync(e);

        }

 

        //当接收完成后

        void ProcessReceive(SocketAsyncEventArgs e)

        {

            //在执行好接收后,本地SOCKET的缓冲区就会被服务器发送的数据填充。

            //显示下信息,当然也是用同步上下文的方式,在显示信息的时候,就直接将缓冲区的字节数组转换成字符串。

            syn.Post(GetText, Encoding.UTF8.GetString(e.Buffer, 0,e.Buffer.Length)+" and Received" );

            //关闭Socket连接

            socket.Close();

            //最后显示下,Socket关闭。

            syn.Post(GetText,"Socket Closed");

        }

 

        //同步上下文调用的方法。

        void GetText(object str)

        {

            txtToSend.Text +="\r\n"+ str.ToString();

        }

 

 

    }

}

 

服务器端,创建一个控制台项目

代码:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Net.Sockets;

using System.Net;

using System.Threading;

using System.IO;

 

namespace ConsoleApp

{

    class Program

    {

        static void Main(string[] args)

        {

            Console.WriteLine("================Socket服务开启======================");

 

            //建立一个子线程,用于创建Socket来监听策略请求和发送。

            ThreadStart pcts = new ThreadStart(PolicyThread);

 

            Thread policythread = new Thread(pcts);

 

            policythread.Start();

 

            //建立一个子线程,用于创建Socket来监听信息请求和发送。

            ThreadStart infots = new ThreadStart(InfoThread);

 

            Thread infothread = new Thread(infots);

 

            infothread.Start();

 

        }

 

        //监听策略请求和发送策略请求方法

        static void PolicyThread()

        {

            //创建一个Socket用来监听943(固定的)端口的策略请求       

            Socket policy = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            policy.Bind(new IPEndPoint(IPAddress.Any, 943));

            policy.Listen(10);

 

            //无限循环监听

            while (true)

            {

                if (policy.Blocking)//如果Socket是阻止模式的(这个东西实际上可以用不)

                {

 

                    //创建Socket,用来获取监听Socket的第一个Socket链接

                    Socket _policy = policy.Accept();

 

                    //定义一个字符串,该字符串与Silverlight发送过来的请求字符串一样。

                    string policyRequestString = "<policy-file-request/>";

 

                    //定义一个字节数组

                    byte[] b = new byte[policyRequestString.Length];

                   

                    //将客户端发送过来,服务器接收到的字节数组存入b

                    _policy.Receive(b);

 

                    //将接收到的字节数组转换成字符串

                    string requeststring = System.Text.Encoding.UTF8.GetString(b, 0, b.Length);

 

                    //显示客户端发送的字符串

                    Console.WriteLine(requeststring);

 

                    //比对客户端发送过来的字符串是否和之前定义的额定好的策略请求字符串相同,如果相同,说明该请求是一个策略请求。

                    if (requeststring == policyRequestString)

                    { 

                        //如果客户端发送的是一个策略请求,服务器发送策略文件到客户端

                        SendPolicy(_policy);

 

                        Console.WriteLine("Policy File have sended");

 

                        //关闭当前连接Socket

                        _policy.Close();

                    }

                    else// 否则,显示错误

                    {

                        Console.WriteLine("not a sure request string!");

                    }

                  

                }

 

            }

        }

 

        //监听信息请求和发送信息方法

        static void InfoThread()

        {

            //创建一个Socket用于监听4502端口,获取接收客户端发送过来的信息

            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            socket.Bind(new IPEndPoint(IPAddress.Any, 4502));

            socket.Listen(10);

 

            //无线循环监听

            while (true)

            {

                //创建Socket,用来获取监听Socket的第一个Socket链接

                Socket _socket = socket.Accept();

 

                //创建一个空字节数组

                byte[] b2 = new byte[1024];

 

                //将接受到的字节数组存入到之前定义的b2字节数组中。

                _socket.Receive(b2);

 

                //显示接收到的信息

                Console.WriteLine(Encoding.UTF8.GetString(b2));

 

                //发回一个信息给客户端,该信息是字节数组,所以我们将信息字符串转换成字节数组

                _socket.Send(Encoding.UTF8.GetBytes("This Send Over!!"));

 

                //关闭当前Socket连接

                _socket.Close();

            }

        }

 

 

        //发送策略文件的方法

        //参数是传递进来的Socket连接

        static void SendPolicy(Socket socket)

        {

            //创建一个文件流,该文件留指定代开一个策略文件,至于策略文件的格式,MSSilverlight有详细说明和配置方法

            FileStream fs = new FileStream(@"D:\WebSites\SilverLight\ConsoleApp\bin\Debug\PolicyFile.xml",FileMode.Open);

 

 

            int length = (int)fs.Length;

 

 

            byte[] bytes = new byte[length];

 

            //将策略文件流读到上面定义的字节数组中

            fs.Read(bytes,0,length);

 

EN-US

分享到:
评论
1 楼 chaochao_pc 2011-08-12  
您好,您的通讯工具能传输文件吗? 我在上边好像没找到!!! 

相关推荐

    SilverLight Socket 异步通讯实例

    在Silverlight中,可以使用`System.Net.Sockets`命名空间中的`Socket`类来实现这一功能。 首先,我们需要创建一个Socket实例并连接到目标服务器。这通常涉及到设置Socket的属性(如协议类型、地址家族和端口),...

    Silverlight Socket

    总结,"Silverlight Socket"项目提供了一个完整的服务端和客户端Socket通信示例,开发者可以通过它学习如何在Silverlight环境中实现Socket通信,这对于理解网络编程和开发实时交互式Web应用至关重要。通过深入研究和...

    Silverlight socket通信Dome

    提供的"SocketDemo"很可能是包含一个完整的Silverlight Socket通信示例项目,包含了客户端和服务器端的代码示例,可以用来学习和理解如何在Silverlight应用中实现Socket通信。 总的来说,Silverlight Socket通信...

    Asp.net + Silverlight Socket多人聊天室源码版

    Silverlight Socket +Asp.net多人聊天室源码版,主要研究Socket通信,有程序包括客户端和服务端。  服务端:实例化Socket, 绑定, 监听, 连接, 接收数据, 发送数据等……  客户端:实例化Socket, 指定服务端地址,...

    silverlight socket 简单 通信 范例

    总结Silverlight中应用Socket的几点特殊之处 1.所有的操作都必须的异步的,包括连接,发送和接收消息 2.Silverlight只能做客户端,不能做服务器(虽然这句看起来说的有点多余,不过确实有朋友想这么做呢) 3....

    silverlight_socket_chat

    本文将围绕“silverlight_socket_chat”这一项目,深入探讨如何使用Silverlight结合Socket技术实现一个聊天室。 首先,我们来看项目的核心——Silverlight。Silverlight是一种插件技术,用于在浏览器中创建富媒体和...

    Silverlight Socket通信

    本文将深入探讨Silverlight中的Socket通信,包括基础概念、使用场景、实现方式以及注意事项。 1. **基础概念** Socket,通常称为套接字,是网络编程中用于进程间通信的一个接口。在Silverlight中,通过Socket类,...

    silverlight+Socket

    客户端源码主要涉及Silverlight UI布局、Socket连接和数据收发的实现;服务器源码则关注Socket监听、连接管理和消息传递的逻辑。通过分析源码,我们可以深入理解如何在实践中结合Silverlight和Socket实现即时通讯...

    silverlight视频聊天Demo

    Silverlight提供了System.Net命名空间,其中包含Socket类,可以用来建立客户端与服务器之间的连接,实现数据的双向传输。 在视频聊天Demo中,可能使用了Silverlight的RIA服务或者WCF(Windows Communication ...

    Silverlight调用Socket程序

    VS2012 程序, 共包括3个Project ,一个Silverlight作为客户端 , 一个网站 ,一个控制台程序作为服务器段, 代码有注释,讲述了Silverlight调用Socket的基本原理。

    silverlight打印实现方案源码

    本文将深入探讨Silverlight中的打印实现方案,以及如何通过源码理解这一功能。 首先,让我们理解Silverlight打印的核心概念。在Silverlight应用中,打印功能允许用户将内容从UI直接输出到打印机,而无需借助操作...

    SilverLight4实现右键菜单效果

    在本文中,我们将深入探讨如何使用Silverlight 4来实现右键菜单效果。Silverlight是一种强大的客户端应用程序开发框架,由Microsoft开发,它允许开发者创建丰富的交互式用户界面,类似于Adobe Flash。右键菜单是用户...

    silverlight控件实现立体翻转效果

    在本文中,我们将深入探讨如何使用Silverlight控件来实现立体翻转效果。Silverlight是一种由微软开发的富客户端技术,用于创建具有丰富媒体体验和交互性功能的Web应用程序。结合Visual Studio 2010和Blend 4,开发者...

    Silverlight实现各种统计图表

    本资源的标题"Silverlight实现各种统计图表"表明它包含了一个使用Silverlight开发的库,用于创建各种类型的统计图表,如柱状图、饼图、线图等,这些图表在数据分析和报告中非常常见。 描述中提到,这是一个DLL...

    silverlight 实现的计算器 源代码

    《基于Silverlight技术实现的计算器源代码解析》 在当今的Web开发领域,Silverlight作为Microsoft推出的一种富互联网应用程序(RIA)平台,曾被广泛应用于创建具有交互性和媒体丰富的用户体验。本篇文章将深入探讨...

    Silverlight音视频socket通信

    Silverlight音视频socket通信,源码

    Silverlight4 Filter实现

    【Silverlight4 Filter实现】 Silverlight 4 是微软推出的一款基于.NET Framework的浏览器插件,用于创建丰富的交互式用户界面,特别是在Web应用中提供多媒体、动画和图形的展示。在Silverlight 4中,"Filter"一词...

    Silverlight实现拖放功能

    在本文中,我们将深入探讨如何在Silverlight应用中实现拖放功能。Silverlight,作为微软开发的一个富互联网应用程序(RIA)平台,允许开发者创建交互性强、具有多媒体元素的Web应用程序。拖放功能是用户界面中常见的...

    silverlight+Wcf实现登录

    在本项目"silverlight+Wcf实现登录"中,我们将探讨如何利用这两种技术来构建一个安全、高效的登录系统。 首先,我们要理解Silverlight在登录界面中的作用。Silverlight应用通常运行在浏览器中,通过XAML...

    Silverlight实现文件下载【很简单】

    本示例“Silverlight实现文件下载【很简单】”聚焦于如何利用Silverlight技术实现在Web应用中进行文件下载的功能。下面我们将详细探讨Silverlight文件下载的原理和实现步骤。 首先,Silverlight文件下载的核心在于...

Global site tag (gtag.js) - Google Analytics