Error[8]: Undefined offset: 829, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

概述 Silverlight下的Socket通讯 分类: Silverlight|WPF 2012-06-17 22:15 1513人阅读 评论(1) 收藏 举报 socket silverlight 服务器 byte string button 本文版权归 博客园 程兴亮 所有,如有转载,请严格按如下方式表明原文作者及出处,以示尊重!! 作者:程兴亮 出处:http://www.cnblogs.  Silverlight下的Socket通讯 分类: Silverlight|WPF 2012-06-17 22:15 1513人阅读 评论(1) 收藏 举报 socket silverlight 服务器 byte string button

本文版权归 博客园 程兴亮 所有,如有转载,请严格按如下方式表明原文作者及出处,以示尊重!!

作者:程兴亮
出处:http://www.cnblogs.com/chengxingliang/archive/2012/05/24/2515100.html

 

  在Silverlight中进行通讯,只能使用4502-4534之间的端口进行数据传输,另外Silverlight客户端会自动向943端口的服务器端发送一个“<policy-file-request/>”的语句请求,然后服务器端943端口回发以下文件以许可Socket通讯。

<?xml version="1.0" enCoding="utf-8" ?><access-policy>  <cross-domain-access>    <policy>      <allow-from>        <domain uri="*"/>      </allow-from>      <grant-to>        <socket-resource port="4502-4534" protocol="tcp"/>      </grant-to>    </policy>  </cross-domain-access></access-policy>

  A.现在我们首先来看服务器端的代码,主要分为策略响应步骤和服务响应步骤。

  策略步骤一:启动监听943端口是否有需要安全策略文件请求

  策略步骤二:如果客户端请求是<policy-file-request/>,则将安全策略文件作为bytes发送给客户端

  服务步骤一:启动服务器端,监听4525端口,是否有Socket对话请求

  服务步骤二:如果有客户端请求的连接,则发送消息告知客户端

  代码如下:

    class Program    {        static voID Main(string[] args)        {            //策略步骤一:启动监听943端口是否有需要安全策略文件请求            Thread access = new Thread(new ThreadStart(accessthread));            access.Start();            //服务步骤一:启动服务器端,监听4525端口,是否有Socket对话请求            Thread server = new Thread(new ThreadStart(ServerThread));            server.Start();        }        //策略请求监听        static voID accessthread()        {            //获取943端口监听的Socket服务端            Socket socket = GetSocketServer(943);            while (true)            {                Socket new_access = socket.Accept();                string clIEntPolicyString = "<policy-file-request/>";                byte[] requestbytes = new byte[clIEntPolicyString.Length];                new_access.Receive(requestbytes);                string requeststring = System.Text.EnCoding.UTF8.GetString(requestbytes,0,requestbytes.Length);                if (requeststring == clIEntPolicyString)                {                    //策略步骤二:如果客户端请求是<policy-file-request/>,则将安全策略文件作为bytes发送给客户端                    byte[] accessbytes = GetPolicyToClIEnt();                    new_access.Send(accessbytes,accessbytes.Length,SocketFlags.None);                    new_access.Close();                }                Thread.Sleep(100);            }        }        static voID ServerThread()        {            //获取4525端口监听的Socket服务端            Socket socket = GetSocketServer(4525);            while (true)            {                Socket _socket = socket.Accept();                //服务步骤二:如果有客户端请求的连接,则发送消息告知客户端                byte[] b2 = new byte[1024];                _socket.Receive(b2);                Console.Writeline(EnCoding.UTF8.GetString(b2).Replace("""",));                string" recString = 我已经收到消息了";                _socket.Send(EnCoding.UTF8.GetBytes(recString));                _socket.Close();                Thread.Sleep(100);            }        }        //根据端口建立Socket服务器端static        int Socket GetSocketServer( serverPort)        {            Socket socket new=  Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);            socket.Bind(new IPEndPoint(IPAddress.Any,serverPort));            socket.Listen(40);            return socket;        }        //获取安全策略文件的byte[]static        byte [] GetPolicyToClIEnt()        {            string" path = Environment.CurrentDirectory.Replace(\bin\DeBUG""",);            fileStream fs new= @" fileStream(path+ \clIEntaccesspolicy.xml",fileMode.Open);            intint length = ()fs.Length;            bytenew[] bytes = byte [length];            fs.Read(bytes,0,length);            fs.Close();            return bytes;        }    }

  B.其次我们来看客户端 *** 作,分为以下几个步骤:

  客户端步骤一:发起服务器连接请求。

  客户端步骤二:连接服务器成功,将需要发送的数据放入缓冲区中,然后异步向服务器发送消息请求

  客户端步骤三:消息发送成功,此时设置一个新的缓冲区实例,并且发起异步接收服务器返回的消息

  客户端步骤四:获取到服务器返回的消息,关闭Socket 

  客户端cs代码如下:

public
    partial class  MainPage : UserControl    {        public MainPage()        {            InitializeComponent();        }        System.Net.sockets.socket socket;        privatevoID object button1_Click( sender,RoutedEventArgs e)        {            bytethis[] userbytes = EnCoding.UTF8.GetBytes(.tbinput.Text);            socket new=  System.Net.sockets.socket(AddressFamily.InterNetwork,ProtocolType.Tcp);            socketasynceventargs socketArgs new=  socketasynceventargs();            socketArgs.RemoteEndPoint new= " DnsEndPoint(127.0.0.1"4525,);            //将需要发送的内容转为byte[],保存到UserToken属性中 userbytes;            socketArgs.Completed             socketArgs.UserToken =new+= (socketArgs_Completed);             EventHandler<socketasynceventargs>//客户端步骤一:发起服务器连接请求。            socket.ConnectAsync(socketArgs);        }        //每发生一个Socket *** 作都讲激活此方法, *** 作包括(Connect/Send/Receive/None)voID        object socketArgs_Completed( sender,socketasynceventargs e)        {            if SocketAsyncoperation.Connect)            {                 (e.Lastoperation ==//客户端步骤二:连接服务器成功,将需要发送的数据放入缓冲区中,然后异步向服务器发送消息请求byte                byte[] userbytes = ([])e.UserToken;                e.SetBuffer(userbytes,userbytes.Length);                socket.SendAsync(e);            }            elseif  SocketAsyncoperation.Send)            {                 (e.Lastoperation ==//客户端步骤三:消息发送成功,此时设置一个新的缓冲区实例,并且发起异步接收服务器返回的消息byte                new[] userbytes = byte 1024[];                e.SetBuffer(userbytes,userbytes.Length);                socket.ReceiveAsync(e);            }            elseif  SocketAsyncoperation.Receive)            {                 (e.Lastoperation ==//客户端步骤四:获取到服务器返回的消息,关闭Socketstring                0 RecevIEStr = EnCoding.UTF8.GetString(e.Buffer,",e.Buffer.Length).Replace(""");                ,//因为是异步Socket请求,所以需要使用UI线程更新lbShowMessage的显示效果thisnew                 DoThingDele(DoThing),RecevIEStr);                socket.Close();            }        }        .lbShowMessage.dispatcher.BeginInvoke(//更新UIpublicvoID        string  arg)        {             DoThing(thisthis".lbShowMessage.Content = ->.lbShowMessage.Content + " arg;        }        // +声明的一个DoThing方法委托publicdelegate        voID string  arg);    } DoThingDele(
"

  客户端Xaml前台代码如下:

LayoutRoot
    <GrID x:name=""White Background=""True ShowGrIDlines=""23>        <TextBox Height=""left HorizontalAlignment=""20,20,0 margin="                  name"tbinput=""top VerticalAlignment=""243 WIDth=""发 送 />        <button Content=""23 Height=""left HorizontalAlignment="                 margin"279,0=""button1 name=""top VerticalAlignment="                 WIDth"75=""button1_Click Click=""28 />        <sdk:Label Height=""left HorizontalAlignment=""20,57,0 margin="                   name"lbShowMessage=""top VerticalAlignment=""358 WIDth="new  />    </GrID>
AsyncCallback

  最后效果如下,如需源码请点击 SLSocket.zip 下载,本文演示的是最简单通讯效果:

 




说说Silverlight里的Socket

作为.Net Framework中的“古董级”类,Socket类无论在1.0,还是最新的3.5 sp1的网络编程里,都占据着极其重要的作用。优化网络架构,一直是开发人员追求的问题。在2.0时代,我们使用异步Socket(Begin、End等方法)来增强性能,不过,这类方法往往要初始化一个IAsyncResult的对象,这给.Net的GC带来了额外的负担。因此,从2.0 sp1起,.Net Framework的Socket类里又多了一种新的异步方式(Async),Silverlight从2.0起,支持通过Async Socket的方式和服务器通信。

Async Socket

首先让我们来看看使用Async方法和以往的使用Begin、End的方法有什么不同吧:

如果是Begin、End的方法,我们采用以下方法来Accept一个客户端:

Server.BeginAccept(protected voID IAsyncResult (DoAcceptTcpClIEntCallBack),Server);

以及CallBack函数:

//获得当前Socket    DoAcceptTcpClIEntCallBack(Socket result){    as SocketListener = result.AsyncState //远程Socket对象    Socket ;    nulltry    clIEnt = //停止同步监听端口        ;    catch    {        returnclIEnt = Listener.EndAccept(result);    }    if {        null;    }    return(clIEnt == StateObject )        new ;    StateObjectstate = //开始异步接收远程Socket发来的数据    SocketFlags(BufferSize);    new clIEnt.BeginReceive(state.Buffer,state.Buffer.Length,AsyncCallback.None,socketasynceventargs new (dobeginReceiveCallback),state);}

如果采用Async方式,则相对简单不少,先初始化一个socketasynceventargs对象:

socketasynceventargsAcceptEventArgs = protected voID object ();AcceptEventArgs.Completed += OnAcceptCompleted;Server.AcceptAsync(AcceptEventArgs);

然后处理Completed事件:

if OnAcceptCompleted(SocketErrorsender,175)">socketasynceventargs e){    Socket (e.socketError == socketasynceventargs .Success)    {        new clIEnt = e.AcceptSocket;        socketasynceventargsargs = new Byte();        args.SetBuffer(if SocketAsyncoperation[10240],10240);        args.Completed += OnClIEntReceive;        clIEnt.ReceiveAsync(args);        Server.AcceptAsync(AcceptEventArgs);    }}
socketasynceventargs

Async Socket的核心部分就是使用socketasynceventargs类,该类专为需要高性能的网络服务器应用程序而设计。应用程序可以完全使用增强的异步模式,也可以仅仅在目标热点区域(例如,在接收大量数据时)使用此模式。

这些增强功能的主要特点是可以避免在异步套接字 I/O 量非常大时发生重复的对象分配和同步。当前由Socket 类实现的开始/结束设计模式要求为每个异步套接字 *** 作分配一个 IAsyncResult 对象。

socketasynceventargs类有一个Completed事件,一切和Async Socket有关的 *** 作结素后,都将调用该事件的处理函数。例如在上面的例子中,我们使用OnAcceptCompleted方法来处理Accept后的结果。通常我们使用此类执行异步套接字 *** 作的模式包含以下步骤:

分配一个新的 socketasynceventargs 上下文对象,或者从应用程序池中获取一个空闲的此类对象。 将该上下文对象的属性设置为要执行的 *** 作(例如,完成回调方法、数据缓冲区、缓冲区偏移量以及要传输的最大数据量)。 调用适当的套接字方法 (xxxAsync) 以启动异步 *** 作。 如果异步套接字方法 (xxxAsync) 返回 true,则在回调中查询上下文属性来获取完成状态。 如果异步套接字方法 (xxxAsync) 返回 false,则说明 *** 作是同步完成的。可以查询上下文属性来获取 *** 作结果。 将该上下文重用于另一个 *** 作,将它放回到应用程序池中,或者将它丢弃。

可以使用同一个socketasynceventargs来处理Accept(服务器)、Connect(客户端)、Send、Receive的结果,socketasynceventargs有一个Lastoperation的属性来标注该Completed是哪种 *** 作的结果:

//…………(e.Lastoperation == else if .Connect){    SocketAsyncoperation}//…………(e.Lastoperation == else if .Receive){    SocketAsyncoperation}//…………(e.Lastoperation == SocketError.Send){    
args.SetBuffer(new Byte[10240],10240);
}

当然,也可以为不同的 *** 作使用不同的socketasynceventargs对象。

可以在事件处理函数中通过观察SocketError属性来判断调用结果,当

e.socketError == 对于上述第二点,我们使用以下形式的策略文件:.Success

表明调用成功。

通过调用socketasynceventargs的SetBuffer方法,来设置需要发送的数据,或指定在接收数据时,的缓存数组。例如在上面例子里,我们为args设置了一个10240字节的数组,来存放接收到的数据:

<?

在Silverlight里使用Async Socket

在Silverlight里使用Async Socket,除了某些方法不支持外,大体上和完整版的.Net类似。不过,也有一些小小的限制:

网络应用程序可以连接到的端口范围必须在 4502-4534 范围内。这些是使用Socket从Silverlight应用程序进行连接所唯一允许使用的端口。如果连接的目标端口不在此端口范围内,则尝试连接时将会失败。 Silverlight 运行时中的安全策略系统要求必须先从网络资源下载一个策略文件,之后才允许网络连接访问该资源。源站点和跨域网络访问都因此而受到影响。

xml

version=1.0enCoding "=" utf-8?><"access-policy">    <cross-domain-access>        <policy>            <allow-from>                <domain uri=file:////>            </"allow-from" >            <grant-to>                <socket-resource port=4502-4506protocol"=" tcp/>            </"grant-to" >        </policy>    </cross-domain-access></access-policy>using using 

可以在服务器上架设一个Server服务,监听943接口。Silverlight通过Socket访问服务器资源时,首先连接到服务器地址的943端口,然后下载该策略文件。

封装好的AsyncclIEnt类

以下是我写的一个可在Silverlight中使用的Async Socket类,用于虚拟实验室里的Socket *** 作。和普通的Socket不同,该类在发送数据包时,在数据包头上添加4字节,作为数据包的长度;接收数据包时,同样的先读取前4字节,作为本次接收的长度。:

using System;using System.Collections.Generic;using System.linq;using System.Text;using System.Net.sockets;using System.IO;using System.Threading;namespace System.Net;public class System.ComponentModel;AsyncclIEnt Newinfosoft.Net.sockets{    INotifyPropertyChanged    #region : /// <summary>        /// {        当接收到数据时        Events        /// </summary>        public event AsyncConnectionEventHandler /// <summary>        /// 当数据发送完毕时        DataRecIEved;        /// </summary>        public event AsyncConnectionEventHandler /// <summary>        /// 当连接服务器成功时        DataSend;        /// </summary>        public event AsyncConnectionEventHandler /// <summary>        /// 当属性改变时(例如是否连接属性)        Connected;        /// </summary>        public event PropertyChangedEventHandler #endregion        /// <summary>        /// PropertyChanged;        用于存放接收时临时数据的内部类        /// 假设服务器发送来的数据格式为:        /// |数据长度n|数据本生        ///    4字节    n字节        /// </summary>        protected class StateObject        public byte/// <summary>            /// {            还有多少字节的数据没有接收            [] Buffer;            /// </summary>            public int public MemoryStream RemainSize = 0;            nullpublic Stream = int ;            new byteStateObject(if bufferSize)            {                Buffer = null[bufferSize];            }            ~StateObject()            {                /// <summary>        /// (Stream != 客户端Socket对象        )                {                    Stream.Close();                    Stream.dispose();                }            }        }        /// </summary>        public Socket getprivate setClIEnt { #region ; public ; }        socketasynceventargs 异步socketasynceventargs        getprivate setSendEventArgs { public ; socketasynceventargs ; }        getprivate setReceiveEventArgs { public ; socketasynceventargs ; }        getprivate setConnectEventArgs { #endregion        ; /// <summary>        /// ; }        读取或设置接收时的StateObject        /// </summary>        protected StateObject getsetState { /// <summary>        /// ; 发送锁,只有当前一个包中的数据全部发送完时,才允许发送下一个包        ; }        /// </summary>        protected object new objectprotected m_lockobject = ManualresetEvent ();        new ManualresetEventSendresetEvent = false#region (protected bool );        falseIsConnecting        /// <summary>        /// m_IsConnecting = 读取或设置是否连接到远程服务器,可用于绑定 *** 作        ;        /// </summary>        public bool get            return IsConnecting        {            set            {                if m_IsConnecting;            }            value{                value(m_IsConnecting != "IsConnecting")                {                    m_IsConnecting = #endregion        ;                    OnPropertyChanged(/// <summary>        /// );                }            }        }        通过指定的IPAddress和Port创建AsyncclIEnt,需要调用Connect方法连接        /// </summary>        /// <param name="bufferSize">接收缓存大小</param>        public int new AsyncclIEnt(StateObjectbufferSize)        {            State = new socketasynceventargs(bufferSize);            SendEventArgs = new socketasynceventargs();            ReceiveEventArgs = false/// <summary>        /// ();            ReceiveEventArgs.Completed += OnReceiveCompleted;            SendEventArgs.Completed += OnSendCompleted;            IsConnecting = 将已有的Socket包装为AsyncclIEnt对象,        ;        }        /// 如果Socket没有连接,则需要调用Connect方法        /// </summary>        /// <param name="socket">Socket对象</param>        /// <param name="bufferSize">接收缓存的大小</param>        public Socket int AsyncclIEnt(new socket,StateObjectbufferSize)        {            State = new socketasynceventargs(bufferSize);                        SendEventArgs = thisif ();            ReceiveEventArgs.Completed += OnReceiveCompleted;            SendEventArgs.Completed += OnSendCompleted;            null .ClIEnt = socket;            true(socket != else            && socket.Connected)            {                ReceiveEventArgs.SetBuffer(State.Buffer,State.Buffer.Length);                ClIEnt.ReceiveAsync(ReceiveEventArgs);                IsConnecting = false;            }            /// <summary>        /// {                IsConnecting = 连接        ;            }        }        /// </summary>        /// <param name="address">IP地址</param>        /// <param name="port">端口号</param>        public voID String int Connect(if address,nullport)        {            new (ClIEnt == Socket)            {                ClIEnt = AddressFamilyif (new .InterNetwork,175)">SocketType.Stream,175)">ProtocolType.Tcp);            }            socketasynceventargs(!ClIEnt.Connected)            {                ConnectEventArgs = EndPoint new ();                ConnectEventArgs.Completed += OnConnectComplete;                IPEndPointremoteEndPoint = IPAddress/// <summary>        /// (发送数据        .Parse(address),port);                ConnectEventArgs.RemoteEndPoint = remoteEndPoint;                ClIEnt.ConnectAsync(ConnectEventArgs);            }        }        /// </summary>        /// <param name="data">需要发送的数据</param>        public voID Byte/// <summary>        /// Send(发送数据,按照以下格式发送数据:        [] data)        {            Send(data,data.Length);        }        /// |数据长度n|需要发送的数据        ///    4字节        n字节        /// </summary>        /// <param name="data">需要发送的数据</param>        /// <param name="offset">需要发送数据的偏移量</param>        /// <param name="size">需要发送数据的长度</param>        public voID Byteint Send(int [] data,if offset,throw new size)        {            Exception(!IsConnecting)            {                "没有连接,无法发送数据!"lock (if );            }            null (m_lockobject)            {                return(data == //计算数据的长度,并转换成字节数组,作为本次发送的头部                || data.Length == 0)                    byte;                BitConverterByte[] length = new .GetBytes(size);                Byte[] buffer = ArrayArray[size + length.Length];                //设置发送Buffer                .copy(length,buffer,length.Length);                //等待发送成功的信息,只有收到该信息,才退出lock锁,                //这样,确保只有当前面得数据发送完后,才发送下一段数据                .copy(data,offset,length.Length,size);                protected voID SendEventArgs.SetBuffer(buffer,buffer.Length);                SendresetEvent.reset();                ClIEnt.SendAsync(SendEventArgs);                string SendresetEvent.WaitOne();            }        }        if OnPropertyChanged(nullpropertyname)        {            this(PropertyChanged != protected voID )            {                PropertyChanged(object ,175)">PropertyChangedEventArgs(propertyname));            }        }        if OnConnectComplete(SocketErrorsender,175)">socketasynceventargs e)        {            true(e.socketError == if .Success)            {                IsConnecting = null;                ReceiveEventArgs.SetBuffer(State.Buffer,State.Buffer.Length);                ClIEnt.ReceiveAsync(ReceiveEventArgs);                this(Connected != null)                {                    Connected(this,175)">AsyncConnectionEventArgs(else            ,false));                }            }            voID {                IsConnecting = object ;            }        }        //如果传输的数据量为0,则表示链接已经断开            OnSendCompleted(if sender,175)">socketasynceventargs e)        {            else            if (e.BytesTransferred == 0)            {                ClIEnt.Close();            }            null{                AsyncConnectionEventArgs (DataSend != new )                {                    AsyncConnectionEventArgsse = thisthis(e.Buffer,//通知数据发送完毕                );                    DataSend(/// <summary>        /// ,se);                }                接收数据处理函数        SendresetEvent.Set();            }        }        /// 1、将收到的数据包中的前4字节转换成Int32类型,作为本次数据包的长度。        /// 2、将这个值设置成StateObject的RemainSize。        /// 3、将数据包中剩下的数据写入StateObject的MemoryStream,并减少相应的RemainSize值。        /// 4、直到RemainSize=0时,表示这一段数据已经接收完毕,从而重复1,开始下一段数据包的接收        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        voID object //如果传输的数据量为0,则表示链接已经断开            OnReceiveCompleted(if sender,175)">socketasynceventargs e)        {            else            int (e.BytesTransferred == 0)            {                ClIEnt.Close();            }            while {                if position = 0;                int (position < e.BytesTransferred)                {                    if (State.RemainSize > 0)                    {                        if bytesToRead = State.RemainSize > e.BytesTransferred - position ?                            e.BytesTransferred - position : State.RemainSize;                        State.RemainSize -= bytesToRead;                        State.Stream.Write(State.Buffer,position,bytesToRead);                        position += bytesToRead;                        null(State.RemainSize == 0)                        {                            AsyncConnectionEventArgs (DataRecIEved != new )                            {                                AsyncConnectionEventArgsce =                                    thisthis(State.Stream.ToArray(),else                    );                                DataRecIEved(BitConverter,ce);                            }                            State.Stream.dispose();                        }                    }                    new {                        State.RemainSize = MemoryStream.ToInt32(State.Buffer,position);                        State.Stream = //重新设置数据缓存区                AsyncclIEnt (State.RemainSize);                        position += 4;                    }                }                new e.SetBuffer(State.Buffer,State.Buffer.Length);                ClIEnt.ReceiveAsync(e);            }        }    }}

使用方式如下:

AsyncclIEntclIEnt= "127.0.0.1"using (10240);clIEnt.Connected += OnClIEntConnected;clIEnt.DataRecIEved += OnClIEntDataRecIEved;clIEnt.Connect(using ,4503);
小节

本文介绍了在Silverlight中,如何使用Async Socket来连接服务器,以及如何编写跨域访问的配置文件。最后,给出了一个适用于Silverlight的类AsyncclIEnt,封装了Async Socket方法。注意,该类在每次发送数据时,需要在数据的前面发送该段数据的长度,因此,只能适用于采用类似方式编写的Server对象:

using System;using System.Collections.Generic;using System.linq;using System.Text;using System.Net.sockets;using System.Net;namespace System.Threading;/// <summary>    /// System.IO;ConnectionServer在.Net 2.0 sp1上的实现    Newinfosoft.Net.sockets{    /// </summary>    public class AsyncServer    #region /// <summary>        /// {        接收到数据        events        /// </summary>        public event AsyncConnectionEventHandler public event AsyncConnectionEventHandler DataRecIEved;        /// <summary>        /// 远程Socket连接        DataSend;        /// </summary>        public event AsyncConnectionEventHandler /// <summary>        /// 开始监听端口        RemoteSocketAccept;        /// </summary>        public event EventHandler /// <summary>        /// 停止监听端口        Started;        /// </summary>        public event EventHandler #endregion        protected class StateObject        Stoped;        public Socket {            nullpublic byteClIEntSocket = public int ;            public [] Buffer;            MemoryStream RemainSize = 0;            nullpublic Stream = int ;            new byteStateObject(/// <summary>        /// bufferSize)            {                Buffer = 读取TCP监听服务        [bufferSize];            }            ~StateObject()            {                Stream.Close();                Stream.dispose();            }        }        /// </summary>        public Socket getprivate setServer        {            /// <summary>        /// ;            读取当前服务的端口号        ;        }        /// </summary>        public int getprivate setPort        {            /// <summary>        /// ;            读取或设置是否正在监听端口        ;        }        /// </summary>        public bool getsetIsListening        {            /// <summary>        /// ;            读取或设置缓存大小        ;        }        /// </summary>        public int getsetBufferSize        {            public ;            socketasynceventargs ;        }        getsetAcceptEventArgs { #region ; /// <summary>        /// ; }        构造函数        构造函数        /// </summary>        /// <param name="port">监听端口</param>        public int thisAsyncServer(/// <summary>        /// port)            : 构造函数        (port,20480)        {        }        /// </summary>        /// <param name="port">监听端口</param>        /// <param name="bufferSize">缓存大小</param>        public int int AsyncServer(#endregion        public voID port,try            bufferSize)        {            Port = port;            BufferSize = bufferSize;        }        if Start()        {            null{                IPEndPoint (Server == new )                {                    IPAddresslocalEP = new Socket.Any,Port);                    Server = inttrue(localEP.AddressFamily,175)">ProtocolType.Tcp);                    Server.Bind(localEP);                }                Server.Listen(if .MaxValue);                IsListening = null;                this(Started != new )                {                    Started(socketasynceventargs,175)">EventArgs());                }                AcceptEventArgs = catch SocketException ();                AcceptEventArgs.Completed += OnAcceptCompleted;                Server.AcceptAsync(AcceptEventArgs);            }            throw (public voID ex)            {                falseex;            }        }        if Stop()        {            IsListening = null;            null(Server != if )            {                Server.Close();                Server = null;                this(Stoped != #region )                {                    Stoped(protected voID ,175)">EventArgs());                }            }        }        object Accept        if OnAcceptCompleted(nullsender,175)">socketasynceventargs e)        {            AsyncclIEnt (e.AcceptSocket.RemoteEndPoint != new )            {                AsyncclIEntclIEnt = if null(e.AcceptSocket,BufferSize);                clIEnt.DataRecIEved += (s2,e2) =>                {                    this(DataRecIEved != if )                    {                        DataRecIEved(null,e2);                    }                };                clIEnt.DataSend += (s2,e2) =>                {                    this(DataSend != //抛出远程Socket连接事件                )                    {                        DataSend(if ,e2);                    }                };                nullthis(RemoteSocketAccept != null)                {                    RemoteSocketAccept(#endregion    ,clIEnt));                }                e.AcceptSocket = [+++];                Server.AcceptAsync(AcceptEventArgs);            }        }        [+++]}}
 总结

以上是内存溢出为你收集整理的Silverlight下的Socket通讯全部内容,希望文章能够帮你解决Silverlight下的Socket通讯所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 165, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Error[8]: Undefined offset: 830, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

概述 Silverlight下的Socket通讯 分类: Silverlight|WPF 2012-06-17 22:15 1513人阅读 评论(1) 收藏 举报 socket silverlight 服务器 byte string button 本文版权归 博客园 程兴亮 所有,如有转载,请严格按如下方式表明原文作者及出处,以示尊重!! 作者:程兴亮 出处:http://www.cnblogs.  Silverlight下的Socket通讯 分类: Silverlight|WPF 2012-06-17 22:15 1513人阅读 评论(1) 收藏 举报 socket silverlight 服务器 byte string button

本文版权归 博客园 程兴亮 所有,如有转载,请严格按如下方式表明原文作者及出处,以示尊重!!

作者:程兴亮
出处:http://www.cnblogs.com/chengxingliang/archive/2012/05/24/2515100.html

 

  在Silverlight中进行通讯,只能使用4502-4534之间的端口进行数据传输,另外Silverlight客户端会自动向943端口的服务器端发送一个“<policy-file-request/>”的语句请求,然后服务器端943端口回发以下文件以许可Socket通讯。

<?xml version="1.0" enCoding="utf-8" ?><access-policy>  <cross-domain-access>    <policy>      <allow-from>        <domain uri="*"/>      </allow-from>      <grant-to>        <socket-resource port="4502-4534" protocol="tcp"/>      </grant-to>    </policy>  </cross-domain-access></access-policy>

  A.现在我们首先来看服务器端的代码,主要分为策略响应步骤和服务响应步骤。

  策略步骤一:启动监听943端口是否有需要安全策略文件请求

  策略步骤二:如果客户端请求是<policy-file-request/>,则将安全策略文件作为bytes发送给客户端

  服务步骤一:启动服务器端,监听4525端口,是否有Socket对话请求

  服务步骤二:如果有客户端请求的连接,则发送消息告知客户端

  代码如下:

    class Program    {        static voID Main(string[] args)        {            //策略步骤一:启动监听943端口是否有需要安全策略文件请求            Thread access = new Thread(new ThreadStart(accessthread));            access.Start();            //服务步骤一:启动服务器端,监听4525端口,是否有Socket对话请求            Thread server = new Thread(new ThreadStart(ServerThread));            server.Start();        }        //策略请求监听        static voID accessthread()        {            //获取943端口监听的Socket服务端            Socket socket = GetSocketServer(943);            while (true)            {                Socket new_access = socket.Accept();                string clIEntPolicyString = "<policy-file-request/>";                byte[] requestbytes = new byte[clIEntPolicyString.Length];                new_access.Receive(requestbytes);                string requeststring = System.Text.EnCoding.UTF8.GetString(requestbytes,0,requestbytes.Length);                if (requeststring == clIEntPolicyString)                {                    //策略步骤二:如果客户端请求是<policy-file-request/>,则将安全策略文件作为bytes发送给客户端                    byte[] accessbytes = GetPolicyToClIEnt();                    new_access.Send(accessbytes,accessbytes.Length,SocketFlags.None);                    new_access.Close();                }                Thread.Sleep(100);            }        }        static voID ServerThread()        {            //获取4525端口监听的Socket服务端            Socket socket = GetSocketServer(4525);            while (true)            {                Socket _socket = socket.Accept();                //服务步骤二:如果有客户端请求的连接,则发送消息告知客户端                byte[] b2 = new byte[1024];                _socket.Receive(b2);                Console.Writeline(EnCoding.UTF8.GetString(b2).Replace("""",));                string" recString = 我已经收到消息了";                _socket.Send(EnCoding.UTF8.GetBytes(recString));                _socket.Close();                Thread.Sleep(100);            }        }        //根据端口建立Socket服务器端static        int Socket GetSocketServer( serverPort)        {            Socket socket new=  Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);            socket.Bind(new IPEndPoint(IPAddress.Any,serverPort));            socket.Listen(40);            return socket;        }        //获取安全策略文件的byte[]static        byte [] GetPolicyToClIEnt()        {            string" path = Environment.CurrentDirectory.Replace(\bin\DeBUG""",);            fileStream fs new= @" fileStream(path+ \clIEntaccesspolicy.xml",fileMode.Open);            intint length = ()fs.Length;            bytenew[] bytes = byte [length];            fs.Read(bytes,0,length);            fs.Close();            return bytes;        }    }

  B.其次我们来看客户端 *** 作,分为以下几个步骤:

  客户端步骤一:发起服务器连接请求。

  客户端步骤二:连接服务器成功,将需要发送的数据放入缓冲区中,然后异步向服务器发送消息请求

  客户端步骤三:消息发送成功,此时设置一个新的缓冲区实例,并且发起异步接收服务器返回的消息

  客户端步骤四:获取到服务器返回的消息,关闭Socket 

  客户端cs代码如下:

public
    partial class  MainPage : UserControl    {        public MainPage()        {            InitializeComponent();        }        System.Net.sockets.socket socket;        privatevoID object button1_Click( sender,RoutedEventArgs e)        {            bytethis[] userbytes = EnCoding.UTF8.GetBytes(.tbinput.Text);            socket new=  System.Net.sockets.socket(AddressFamily.InterNetwork,ProtocolType.Tcp);            socketasynceventargs socketArgs new=  socketasynceventargs();            socketArgs.RemoteEndPoint new= " DnsEndPoint(127.0.0.1"4525,);            //将需要发送的内容转为byte[],保存到UserToken属性中 userbytes;            socketArgs.Completed             socketArgs.UserToken =new+= (socketArgs_Completed);             EventHandler<socketasynceventargs>//客户端步骤一:发起服务器连接请求。            socket.ConnectAsync(socketArgs);        }        //每发生一个Socket *** 作都讲激活此方法, *** 作包括(Connect/Send/Receive/None)voID        object socketArgs_Completed( sender,socketasynceventargs e)        {            if SocketAsyncoperation.Connect)            {                 (e.Lastoperation ==//客户端步骤二:连接服务器成功,将需要发送的数据放入缓冲区中,然后异步向服务器发送消息请求byte                byte[] userbytes = ([])e.UserToken;                e.SetBuffer(userbytes,userbytes.Length);                socket.SendAsync(e);            }            elseif  SocketAsyncoperation.Send)            {                 (e.Lastoperation ==//客户端步骤三:消息发送成功,此时设置一个新的缓冲区实例,并且发起异步接收服务器返回的消息byte                new[] userbytes = byte 1024[];                e.SetBuffer(userbytes,userbytes.Length);                socket.ReceiveAsync(e);            }            elseif  SocketAsyncoperation.Receive)            {                 (e.Lastoperation ==//客户端步骤四:获取到服务器返回的消息,关闭Socketstring                0 RecevIEStr = EnCoding.UTF8.GetString(e.Buffer,",e.Buffer.Length).Replace(""");                ,//因为是异步Socket请求,所以需要使用UI线程更新lbShowMessage的显示效果thisnew                 DoThingDele(DoThing),RecevIEStr);                socket.Close();            }        }        .lbShowMessage.dispatcher.BeginInvoke(//更新UIpublicvoID        string  arg)        {             DoThing(thisthis".lbShowMessage.Content = ->.lbShowMessage.Content + " arg;        }        // +声明的一个DoThing方法委托publicdelegate        voID string  arg);    } DoThingDele(
"

  客户端Xaml前台代码如下:

LayoutRoot
    <GrID x:name=""White Background=""True ShowGrIDlines=""23>        <TextBox Height=""left HorizontalAlignment=""20,20,0 margin="                  name"tbinput=""top VerticalAlignment=""243 WIDth=""发 送 />        <button Content=""23 Height=""left HorizontalAlignment="                 margin"279,0=""button1 name=""top VerticalAlignment="                 WIDth"75=""button1_Click Click=""28 />        <sdk:Label Height=""left HorizontalAlignment=""20,57,0 margin="                   name"lbShowMessage=""top VerticalAlignment=""358 WIDth="new  />    </GrID>
AsyncCallback

  最后效果如下,如需源码请点击 SLSocket.zip 下载,本文演示的是最简单通讯效果:

 




说说Silverlight里的Socket

作为.Net Framework中的“古董级”类,Socket类无论在1.0,还是最新的3.5 sp1的网络编程里,都占据着极其重要的作用。优化网络架构,一直是开发人员追求的问题。在2.0时代,我们使用异步Socket(Begin、End等方法)来增强性能,不过,这类方法往往要初始化一个IAsyncResult的对象,这给.Net的GC带来了额外的负担。因此,从2.0 sp1起,.Net Framework的Socket类里又多了一种新的异步方式(Async),Silverlight从2.0起,支持通过Async Socket的方式和服务器通信。

Async Socket

首先让我们来看看使用Async方法和以往的使用Begin、End的方法有什么不同吧:

如果是Begin、End的方法,我们采用以下方法来Accept一个客户端:

Server.BeginAccept(protected voID IAsyncResult (DoAcceptTcpClIEntCallBack),Server);

以及CallBack函数:

//获得当前Socket    DoAcceptTcpClIEntCallBack(Socket result){    as SocketListener = result.AsyncState //远程Socket对象    Socket ;    nulltry    clIEnt = //停止同步监听端口        ;    catch    {        returnclIEnt = Listener.EndAccept(result);    }    if {        null;    }    return(clIEnt == StateObject )        new ;    StateObjectstate = //开始异步接收远程Socket发来的数据    SocketFlags(BufferSize);    new clIEnt.BeginReceive(state.Buffer,state.Buffer.Length,AsyncCallback.None,socketasynceventargs new (dobeginReceiveCallback),state);}

如果采用Async方式,则相对简单不少,先初始化一个socketasynceventargs对象:

socketasynceventargsAcceptEventArgs = protected voID object ();AcceptEventArgs.Completed += OnAcceptCompleted;Server.AcceptAsync(AcceptEventArgs);

然后处理Completed事件:

if OnAcceptCompleted(SocketErrorsender,175)">socketasynceventargs e){    Socket (e.socketError == socketasynceventargs .Success)    {        new clIEnt = e.AcceptSocket;        socketasynceventargsargs = new Byte();        args.SetBuffer(if SocketAsyncoperation[10240],10240);        args.Completed += OnClIEntReceive;        clIEnt.ReceiveAsync(args);        Server.AcceptAsync(AcceptEventArgs);    }}
socketasynceventargs

Async Socket的核心部分就是使用socketasynceventargs类,该类专为需要高性能的网络服务器应用程序而设计。应用程序可以完全使用增强的异步模式,也可以仅仅在目标热点区域(例如,在接收大量数据时)使用此模式。

这些增强功能的主要特点是可以避免在异步套接字 I/O 量非常大时发生重复的对象分配和同步。当前由Socket 类实现的开始/结束设计模式要求为每个异步套接字 *** 作分配一个 IAsyncResult 对象。

socketasynceventargs类有一个Completed事件,一切和Async Socket有关的 *** 作结素后,都将调用该事件的处理函数。例如在上面的例子中,我们使用OnAcceptCompleted方法来处理Accept后的结果。通常我们使用此类执行异步套接字 *** 作的模式包含以下步骤:

分配一个新的 socketasynceventargs 上下文对象,或者从应用程序池中获取一个空闲的此类对象。 将该上下文对象的属性设置为要执行的 *** 作(例如,完成回调方法、数据缓冲区、缓冲区偏移量以及要传输的最大数据量)。 调用适当的套接字方法 (xxxAsync) 以启动异步 *** 作。 如果异步套接字方法 (xxxAsync) 返回 true,则在回调中查询上下文属性来获取完成状态。 如果异步套接字方法 (xxxAsync) 返回 false,则说明 *** 作是同步完成的。可以查询上下文属性来获取 *** 作结果。 将该上下文重用于另一个 *** 作,将它放回到应用程序池中,或者将它丢弃。

可以使用同一个socketasynceventargs来处理Accept(服务器)、Connect(客户端)、Send、Receive的结果,socketasynceventargs有一个Lastoperation的属性来标注该Completed是哪种 *** 作的结果:

//…………(e.Lastoperation == else if .Connect){    SocketAsyncoperation}//…………(e.Lastoperation == else if .Receive){    SocketAsyncoperation}//…………(e.Lastoperation == SocketError.Send){    
args.SetBuffer(new Byte[10240],10240);
}

当然,也可以为不同的 *** 作使用不同的socketasynceventargs对象。

可以在事件处理函数中通过观察SocketError属性来判断调用结果,当

e.socketError == 对于上述第二点,我们使用以下形式的策略文件:.Success

表明调用成功。

通过调用socketasynceventargs的SetBuffer方法,来设置需要发送的数据,或指定在接收数据时,的缓存数组。例如在上面例子里,我们为args设置了一个10240字节的数组,来存放接收到的数据:

<?

在Silverlight里使用Async Socket

在Silverlight里使用Async Socket,除了某些方法不支持外,大体上和完整版的.Net类似。不过,也有一些小小的限制:

网络应用程序可以连接到的端口范围必须在 4502-4534 范围内。这些是使用Socket从Silverlight应用程序进行连接所唯一允许使用的端口。如果连接的目标端口不在此端口范围内,则尝试连接时将会失败。 Silverlight 运行时中的安全策略系统要求必须先从网络资源下载一个策略文件,之后才允许网络连接访问该资源。源站点和跨域网络访问都因此而受到影响。

xml

version=1.0enCoding "=" utf-8?><"access-policy">    <cross-domain-access>        <policy>            <allow-from>                <domain uri=file:////>            </"allow-from" >            <grant-to>                <socket-resource port=4502-4506protocol"=" tcp/>            </"grant-to" >        </policy>    </cross-domain-access></access-policy>using using 

可以在服务器上架设一个Server服务,监听943接口。Silverlight通过Socket访问服务器资源时,首先连接到服务器地址的943端口,然后下载该策略文件。

封装好的AsyncclIEnt类

以下是我写的一个可在Silverlight中使用的Async Socket类,用于虚拟实验室里的Socket *** 作。和普通的Socket不同,该类在发送数据包时,在数据包头上添加4字节,作为数据包的长度;接收数据包时,同样的先读取前4字节,作为本次接收的长度。:

using System;using System.Collections.Generic;using System.linq;using System.Text;using System.Net.sockets;using System.IO;using System.Threading;namespace System.Net;public class System.ComponentModel;AsyncclIEnt Newinfosoft.Net.sockets{    INotifyPropertyChanged    #region : /// <summary>        /// {        当接收到数据时        Events        /// </summary>        public event AsyncConnectionEventHandler /// <summary>        /// 当数据发送完毕时        DataRecIEved;        /// </summary>        public event AsyncConnectionEventHandler /// <summary>        /// 当连接服务器成功时        DataSend;        /// </summary>        public event AsyncConnectionEventHandler /// <summary>        /// 当属性改变时(例如是否连接属性)        Connected;        /// </summary>        public event PropertyChangedEventHandler #endregion        /// <summary>        /// PropertyChanged;        用于存放接收时临时数据的内部类        /// 假设服务器发送来的数据格式为:        /// |数据长度n|数据本生        ///    4字节    n字节        /// </summary>        protected class StateObject        public byte/// <summary>            /// {            还有多少字节的数据没有接收            [] Buffer;            /// </summary>            public int public MemoryStream RemainSize = 0;            nullpublic Stream = int ;            new byteStateObject(if bufferSize)            {                Buffer = null[bufferSize];            }            ~StateObject()            {                /// <summary>        /// (Stream != 客户端Socket对象        )                {                    Stream.Close();                    Stream.dispose();                }            }        }        /// </summary>        public Socket getprivate setClIEnt { #region ; public ; }        socketasynceventargs 异步socketasynceventargs        getprivate setSendEventArgs { public ; socketasynceventargs ; }        getprivate setReceiveEventArgs { public ; socketasynceventargs ; }        getprivate setConnectEventArgs { #endregion        ; /// <summary>        /// ; }        读取或设置接收时的StateObject        /// </summary>        protected StateObject getsetState { /// <summary>        /// ; 发送锁,只有当前一个包中的数据全部发送完时,才允许发送下一个包        ; }        /// </summary>        protected object new objectprotected m_lockobject = ManualresetEvent ();        new ManualresetEventSendresetEvent = false#region (protected bool );        falseIsConnecting        /// <summary>        /// m_IsConnecting = 读取或设置是否连接到远程服务器,可用于绑定 *** 作        ;        /// </summary>        public bool get            return IsConnecting        {            set            {                if m_IsConnecting;            }            value{                value(m_IsConnecting != "IsConnecting")                {                    m_IsConnecting = #endregion        ;                    OnPropertyChanged(/// <summary>        /// );                }            }        }        通过指定的IPAddress和Port创建AsyncclIEnt,需要调用Connect方法连接        /// </summary>        /// <param name="bufferSize">接收缓存大小</param>        public int new AsyncclIEnt(StateObjectbufferSize)        {            State = new socketasynceventargs(bufferSize);            SendEventArgs = new socketasynceventargs();            ReceiveEventArgs = false/// <summary>        /// ();            ReceiveEventArgs.Completed += OnReceiveCompleted;            SendEventArgs.Completed += OnSendCompleted;            IsConnecting = 将已有的Socket包装为AsyncclIEnt对象,        ;        }        /// 如果Socket没有连接,则需要调用Connect方法        /// </summary>        /// <param name="socket">Socket对象</param>        /// <param name="bufferSize">接收缓存的大小</param>        public Socket int AsyncclIEnt(new socket,StateObjectbufferSize)        {            State = new socketasynceventargs(bufferSize);                        SendEventArgs = thisif ();            ReceiveEventArgs.Completed += OnReceiveCompleted;            SendEventArgs.Completed += OnSendCompleted;            null .ClIEnt = socket;            true(socket != else            && socket.Connected)            {                ReceiveEventArgs.SetBuffer(State.Buffer,State.Buffer.Length);                ClIEnt.ReceiveAsync(ReceiveEventArgs);                IsConnecting = false;            }            /// <summary>        /// {                IsConnecting = 连接        ;            }        }        /// </summary>        /// <param name="address">IP地址</param>        /// <param name="port">端口号</param>        public voID String int Connect(if address,nullport)        {            new (ClIEnt == Socket)            {                ClIEnt = AddressFamilyif (new .InterNetwork,175)">SocketType.Stream,175)">ProtocolType.Tcp);            }            socketasynceventargs(!ClIEnt.Connected)            {                ConnectEventArgs = EndPoint new ();                ConnectEventArgs.Completed += OnConnectComplete;                IPEndPointremoteEndPoint = IPAddress/// <summary>        /// (发送数据        .Parse(address),port);                ConnectEventArgs.RemoteEndPoint = remoteEndPoint;                ClIEnt.ConnectAsync(ConnectEventArgs);            }        }        /// </summary>        /// <param name="data">需要发送的数据</param>        public voID Byte/// <summary>        /// Send(发送数据,按照以下格式发送数据:        [] data)        {            Send(data,data.Length);        }        /// |数据长度n|需要发送的数据        ///    4字节        n字节        /// </summary>        /// <param name="data">需要发送的数据</param>        /// <param name="offset">需要发送数据的偏移量</param>        /// <param name="size">需要发送数据的长度</param>        public voID Byteint Send(int [] data,if offset,throw new size)        {            Exception(!IsConnecting)            {                "没有连接,无法发送数据!"lock (if );            }            null (m_lockobject)            {                return(data == //计算数据的长度,并转换成字节数组,作为本次发送的头部                || data.Length == 0)                    byte;                BitConverterByte[] length = new .GetBytes(size);                Byte[] buffer = ArrayArray[size + length.Length];                //设置发送Buffer                .copy(length,buffer,length.Length);                //等待发送成功的信息,只有收到该信息,才退出lock锁,                //这样,确保只有当前面得数据发送完后,才发送下一段数据                .copy(data,offset,length.Length,size);                protected voID SendEventArgs.SetBuffer(buffer,buffer.Length);                SendresetEvent.reset();                ClIEnt.SendAsync(SendEventArgs);                string SendresetEvent.WaitOne();            }        }        if OnPropertyChanged(nullpropertyname)        {            this(PropertyChanged != protected voID )            {                PropertyChanged(object ,175)">PropertyChangedEventArgs(propertyname));            }        }        if OnConnectComplete(SocketErrorsender,175)">socketasynceventargs e)        {            true(e.socketError == if .Success)            {                IsConnecting = null;                ReceiveEventArgs.SetBuffer(State.Buffer,State.Buffer.Length);                ClIEnt.ReceiveAsync(ReceiveEventArgs);                this(Connected != null)                {                    Connected(this,175)">AsyncConnectionEventArgs(else            ,false));                }            }            voID {                IsConnecting = object ;            }        }        //如果传输的数据量为0,则表示链接已经断开            OnSendCompleted(if sender,175)">socketasynceventargs e)        {            else            if (e.BytesTransferred == 0)            {                ClIEnt.Close();            }            null{                AsyncConnectionEventArgs (DataSend != new )                {                    AsyncConnectionEventArgsse = thisthis(e.Buffer,//通知数据发送完毕                );                    DataSend(/// <summary>        /// ,se);                }                接收数据处理函数        SendresetEvent.Set();            }        }        /// 1、将收到的数据包中的前4字节转换成Int32类型,作为本次数据包的长度。        /// 2、将这个值设置成StateObject的RemainSize。        /// 3、将数据包中剩下的数据写入StateObject的MemoryStream,并减少相应的RemainSize值。        /// 4、直到RemainSize=0时,表示这一段数据已经接收完毕,从而重复1,开始下一段数据包的接收        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        voID object //如果传输的数据量为0,则表示链接已经断开            OnReceiveCompleted(if sender,175)">socketasynceventargs e)        {            else            int (e.BytesTransferred == 0)            {                ClIEnt.Close();            }            while {                if position = 0;                int (position < e.BytesTransferred)                {                    if (State.RemainSize > 0)                    {                        if bytesToRead = State.RemainSize > e.BytesTransferred - position ?                            e.BytesTransferred - position : State.RemainSize;                        State.RemainSize -= bytesToRead;                        State.Stream.Write(State.Buffer,position,bytesToRead);                        position += bytesToRead;                        null(State.RemainSize == 0)                        {                            AsyncConnectionEventArgs (DataRecIEved != new )                            {                                AsyncConnectionEventArgsce =                                    thisthis(State.Stream.ToArray(),else                    );                                DataRecIEved(BitConverter,ce);                            }                            State.Stream.dispose();                        }                    }                    new {                        State.RemainSize = MemoryStream.ToInt32(State.Buffer,position);                        State.Stream = //重新设置数据缓存区                AsyncclIEnt (State.RemainSize);                        position += 4;                    }                }                new e.SetBuffer(State.Buffer,State.Buffer.Length);                ClIEnt.ReceiveAsync(e);            }        }    }}

使用方式如下:

AsyncclIEntclIEnt= "127.0.0.1"using (10240);clIEnt.Connected += OnClIEntConnected;clIEnt.DataRecIEved += OnClIEntDataRecIEved;clIEnt.Connect(using ,4503);
小节

本文介绍了在Silverlight中,如何使用Async Socket来连接服务器,以及如何编写跨域访问的配置文件。最后,给出了一个适用于Silverlight的类AsyncclIEnt,封装了Async Socket方法。注意,该类在每次发送数据时,需要在数据的前面发送该段数据的长度,因此,只能适用于采用类似方式编写的Server对象:

using System;using System.Collections.Generic;using System.linq;using System.Text;using System.Net.sockets;using System.Net;namespace System.Threading;/// <summary>    /// System.IO;ConnectionServer在.Net 2.0 sp1上的实现    Newinfosoft.Net.sockets{    /// </summary>    public class AsyncServer    #region /// <summary>        /// {        接收到数据        events        /// </summary>        public event AsyncConnectionEventHandler public event AsyncConnectionEventHandler DataRecIEved;        /// <summary>        /// 远程Socket连接        DataSend;        /// </summary>        public event AsyncConnectionEventHandler /// <summary>        /// 开始监听端口        RemoteSocketAccept;        /// </summary>        public event EventHandler /// <summary>        /// 停止监听端口        Started;        /// </summary>        public event EventHandler #endregion        protected class StateObject        Stoped;        public Socket {            nullpublic byteClIEntSocket = public int ;            public [] Buffer;            MemoryStream RemainSize = 0;            nullpublic Stream = int ;            new byteStateObject(/// <summary>        /// bufferSize)            {                Buffer = 读取TCP监听服务        [bufferSize];            }            ~StateObject()            {                Stream.Close();                Stream.dispose();            }        }        /// </summary>        public Socket getprivate setServer        {            /// <summary>        /// ;            读取当前服务的端口号        ;        }        /// </summary>        public int getprivate setPort        {            /// <summary>        /// ;            读取或设置是否正在监听端口        ;        }        /// </summary>        public bool getsetIsListening        {            /// <summary>        /// ;            读取或设置缓存大小        ;        }        /// </summary>        public int getsetBufferSize        {            public ;            socketasynceventargs ;        }        getsetAcceptEventArgs { #region ; /// <summary>        /// ; }        构造函数        构造函数        /// </summary>        /// <param name="port">监听端口</param>        public int thisAsyncServer(/// <summary>        /// port)            : 构造函数        (port,20480)        {        }        /// </summary>        /// <param name="port">监听端口</param>        /// <param name="bufferSize">缓存大小</param>        public int int AsyncServer(#endregion        public voID port,try            bufferSize)        {            Port = port;            BufferSize = bufferSize;        }        if Start()        {            null{                IPEndPoint (Server == new )                {                    IPAddresslocalEP = new Socket.Any,Port);                    Server = inttrue(localEP.AddressFamily,175)">ProtocolType.Tcp);                    Server.Bind(localEP);                }                Server.Listen(if .MaxValue);                IsListening = null;                this(Started != new )                {                    Started(socketasynceventargs,175)">EventArgs());                }                AcceptEventArgs = catch SocketException ();                AcceptEventArgs.Completed += OnAcceptCompleted;                Server.AcceptAsync(AcceptEventArgs);            }            throw (public voID ex)            {                falseex;            }        }        if Stop()        {            IsListening = null;            null(Server != if )            {                Server.Close();                Server = null;                this(Stoped != #region )                {                    Stoped(protected voID ,175)">EventArgs());                }            }        }        object Accept        if OnAcceptCompleted(nullsender,175)">socketasynceventargs e)        {            AsyncclIEnt (e.AcceptSocket.RemoteEndPoint != new )            {                AsyncclIEntclIEnt = if null(e.AcceptSocket,BufferSize);                clIEnt.DataRecIEved += (s2,e2) =>                {                    this(DataRecIEved != if )                    {                        DataRecIEved(null,e2);                    }                };                clIEnt.DataSend += (s2,e2) =>                {                    this(DataSend != //抛出远程Socket连接事件                )                    {                        DataSend(if ,e2);                    }                };                nullthis(RemoteSocketAccept != null)                {                    RemoteSocketAccept(#endregion    ,clIEnt));                }                e.AcceptSocket = ;                Server.AcceptAsync(AcceptEventArgs);            }        }        [+++]}}
 总结

以上是内存溢出为你收集整理的Silverlight下的Socket通讯全部内容,希望文章能够帮你解决Silverlight下的Socket通讯所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 165, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Silverlight下的Socket通讯_app_内存溢出

Silverlight下的Socket通讯

Silverlight下的Socket通讯,第1张

概述 Silverlight下的Socket通讯 分类: Silverlight|WPF 2012-06-17 22:15 1513人阅读 评论(1) 收藏 举报 socket silverlight 服务器 byte string button 本文版权归 博客园 程兴亮 所有,如有转载,请严格按如下方式表明原文作者及出处,以示尊重!! 作者:程兴亮 出处:http://www.cnblogs.  Silverlight下的Socket通讯 分类: Silverlight|WPF 2012-06-17 22:15 1513人阅读 评论(1) 收藏 举报 socket silverlight 服务器 byte string button

本文版权归 博客园 程兴亮 所有,如有转载,请严格按如下方式表明原文作者及出处,以示尊重!!

作者:程兴亮
出处:http://www.cnblogs.com/chengxingliang/archive/2012/05/24/2515100.html

 

  在Silverlight中进行通讯,只能使用4502-4534之间的端口进行数据传输,另外Silverlight客户端会自动向943端口的服务器端发送一个“<policy-file-request/>”的语句请求,然后服务器端943端口回发以下文件以许可Socket通讯。

<?xml version="1.0" enCoding="utf-8" ?><access-policy>  <cross-domain-access>    <policy>      <allow-from>        <domain uri="*"/>      </allow-from>      <grant-to>        <socket-resource port="4502-4534" protocol="tcp"/>      </grant-to>    </policy>  </cross-domain-access></access-policy>

  A.现在我们首先来看服务器端的代码,主要分为策略响应步骤和服务响应步骤。

  策略步骤一:启动监听943端口是否有需要安全策略文件请求

  策略步骤二:如果客户端请求是<policy-file-request/>,则将安全策略文件作为bytes发送给客户端

  服务步骤一:启动服务器端,监听4525端口,是否有Socket对话请求

  服务步骤二:如果有客户端请求的连接,则发送消息告知客户端

  代码如下:

    class Program    {        static voID Main(string[] args)        {            //策略步骤一:启动监听943端口是否有需要安全策略文件请求            Thread access = new Thread(new ThreadStart(accessthread));            access.Start();            //服务步骤一:启动服务器端,监听4525端口,是否有Socket对话请求            Thread server = new Thread(new ThreadStart(ServerThread));            server.Start();        }        //策略请求监听        static voID accessthread()        {            //获取943端口监听的Socket服务端            Socket socket = GetSocketServer(943);            while (true)            {                Socket new_access = socket.Accept();                string clIEntPolicyString = "<policy-file-request/>";                byte[] requestbytes = new byte[clIEntPolicyString.Length];                new_access.Receive(requestbytes);                string requeststring = System.Text.EnCoding.UTF8.GetString(requestbytes,0,requestbytes.Length);                if (requeststring == clIEntPolicyString)                {                    //策略步骤二:如果客户端请求是<policy-file-request/>,则将安全策略文件作为bytes发送给客户端                    byte[] accessbytes = GetPolicyToClIEnt();                    new_access.Send(accessbytes,accessbytes.Length,SocketFlags.None);                    new_access.Close();                }                Thread.Sleep(100);            }        }        static voID ServerThread()        {            //获取4525端口监听的Socket服务端            Socket socket = GetSocketServer(4525);            while (true)            {                Socket _socket = socket.Accept();                //服务步骤二:如果有客户端请求的连接,则发送消息告知客户端                byte[] b2 = new byte[1024];                _socket.Receive(b2);                Console.Writeline(EnCoding.UTF8.GetString(b2).Replace("""",));                string" recString = 我已经收到消息了";                _socket.Send(EnCoding.UTF8.GetBytes(recString));                _socket.Close();                Thread.Sleep(100);            }        }        //根据端口建立Socket服务器端static        int Socket GetSocketServer( serverPort)        {            Socket socket new=  Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);            socket.Bind(new IPEndPoint(IPAddress.Any,serverPort));            socket.Listen(40);            return socket;        }        //获取安全策略文件的byte[]static        byte [] GetPolicyToClIEnt()        {            string" path = Environment.CurrentDirectory.Replace(\bin\DeBUG""",);            fileStream fs new= @" fileStream(path+ \clIEntaccesspolicy.xml",fileMode.Open);            intint length = ()fs.Length;            bytenew[] bytes = byte [length];            fs.Read(bytes,0,length);            fs.Close();            return bytes;        }    }

  B.其次我们来看客户端 *** 作,分为以下几个步骤:

  客户端步骤一:发起服务器连接请求。

  客户端步骤二:连接服务器成功,将需要发送的数据放入缓冲区中,然后异步向服务器发送消息请求

  客户端步骤三:消息发送成功,此时设置一个新的缓冲区实例,并且发起异步接收服务器返回的消息

  客户端步骤四:获取到服务器返回的消息,关闭Socket 

  客户端cs代码如下:

public
    partial class  MainPage : UserControl    {        public MainPage()        {            InitializeComponent();        }        System.Net.sockets.socket socket;        privatevoID object button1_Click( sender,RoutedEventArgs e)        {            bytethis[] userbytes = EnCoding.UTF8.GetBytes(.tbinput.Text);            socket new=  System.Net.sockets.socket(AddressFamily.InterNetwork,ProtocolType.Tcp);            socketasynceventargs socketArgs new=  socketasynceventargs();            socketArgs.RemoteEndPoint new= " DnsEndPoint(127.0.0.1"4525,);            //将需要发送的内容转为byte[],保存到UserToken属性中 userbytes;            socketArgs.Completed             socketArgs.UserToken =new+= (socketArgs_Completed);             EventHandler<socketasynceventargs>//客户端步骤一:发起服务器连接请求。            socket.ConnectAsync(socketArgs);        }        //每发生一个Socket *** 作都讲激活此方法, *** 作包括(Connect/Send/Receive/None)voID        object socketArgs_Completed( sender,socketasynceventargs e)        {            if SocketAsyncoperation.Connect)            {                 (e.Lastoperation ==//客户端步骤二:连接服务器成功,将需要发送的数据放入缓冲区中,然后异步向服务器发送消息请求byte                byte[] userbytes = ([])e.UserToken;                e.SetBuffer(userbytes,userbytes.Length);                socket.SendAsync(e);            }            elseif  SocketAsyncoperation.Send)            {                 (e.Lastoperation ==//客户端步骤三:消息发送成功,此时设置一个新的缓冲区实例,并且发起异步接收服务器返回的消息byte                new[] userbytes = byte 1024[];                e.SetBuffer(userbytes,userbytes.Length);                socket.ReceiveAsync(e);            }            elseif  SocketAsyncoperation.Receive)            {                 (e.Lastoperation ==//客户端步骤四:获取到服务器返回的消息,关闭Socketstring                0 RecevIEStr = EnCoding.UTF8.GetString(e.Buffer,",e.Buffer.Length).Replace(""");                ,//因为是异步Socket请求,所以需要使用UI线程更新lbShowMessage的显示效果thisnew                 DoThingDele(DoThing),RecevIEStr);                socket.Close();            }        }        .lbShowMessage.dispatcher.BeginInvoke(//更新UIpublicvoID        string  arg)        {             DoThing(thisthis".lbShowMessage.Content = ->.lbShowMessage.Content + " arg;        }        // +声明的一个DoThing方法委托publicdelegate        voID string  arg);    } DoThingDele(
"

  客户端Xaml前台代码如下:

LayoutRoot
    <GrID x:name=""White Background=""True ShowGrIDlines=""23>        <TextBox Height=""left HorizontalAlignment=""20,20,0 margin="                  name"tbinput=""top VerticalAlignment=""243 WIDth=""发 送 />        <button Content=""23 Height=""left HorizontalAlignment="                 margin"279,0=""button1 name=""top VerticalAlignment="                 WIDth"75=""button1_Click Click=""28 />        <sdk:Label Height=""left HorizontalAlignment=""20,57,0 margin="                   name"lbShowMessage=""top VerticalAlignment=""358 WIDth="new  />    </GrID>
AsyncCallback

  最后效果如下,如需源码请点击 SLSocket.zip 下载,本文演示的是最简单通讯效果:

 




说说Silverlight里的Socket

作为.Net Framework中的“古董级”类,Socket类无论在1.0,还是最新的3.5 sp1的网络编程里,都占据着极其重要的作用。优化网络架构,一直是开发人员追求的问题。在2.0时代,我们使用异步Socket(Begin、End等方法)来增强性能,不过,这类方法往往要初始化一个IAsyncResult的对象,这给.Net的GC带来了额外的负担。因此,从2.0 sp1起,.Net Framework的Socket类里又多了一种新的异步方式(Async),Silverlight从2.0起,支持通过Async Socket的方式和服务器通信。

Async Socket

首先让我们来看看使用Async方法和以往的使用Begin、End的方法有什么不同吧:

如果是Begin、End的方法,我们采用以下方法来Accept一个客户端:

Server.BeginAccept(protected voID IAsyncResult (DoAcceptTcpClIEntCallBack),Server);

以及CallBack函数:

//获得当前Socket    DoAcceptTcpClIEntCallBack(Socket result){    as SocketListener = result.AsyncState //远程Socket对象    Socket ;    nulltry    clIEnt = //停止同步监听端口        ;    catch    {        returnclIEnt = Listener.EndAccept(result);    }    if {        null;    }    return(clIEnt == StateObject )        new ;    StateObjectstate = //开始异步接收远程Socket发来的数据    SocketFlags(BufferSize);    new clIEnt.BeginReceive(state.Buffer,state.Buffer.Length,AsyncCallback.None,socketasynceventargs new (dobeginReceiveCallback),state);}

如果采用Async方式,则相对简单不少,先初始化一个socketasynceventargs对象:

socketasynceventargsAcceptEventArgs = protected voID object ();AcceptEventArgs.Completed += OnAcceptCompleted;Server.AcceptAsync(AcceptEventArgs);

然后处理Completed事件:

if OnAcceptCompleted(SocketErrorsender,175)">socketasynceventargs e){    Socket (e.socketError == socketasynceventargs .Success)    {        new clIEnt = e.AcceptSocket;        socketasynceventargsargs = new Byte();        args.SetBuffer(if SocketAsyncoperation[10240],10240);        args.Completed += OnClIEntReceive;        clIEnt.ReceiveAsync(args);        Server.AcceptAsync(AcceptEventArgs);    }}
socketasynceventargs

Async Socket的核心部分就是使用socketasynceventargs类,该类专为需要高性能的网络服务器应用程序而设计。应用程序可以完全使用增强的异步模式,也可以仅仅在目标热点区域(例如,在接收大量数据时)使用此模式。

这些增强功能的主要特点是可以避免在异步套接字 I/O 量非常大时发生重复的对象分配和同步。当前由Socket 类实现的开始/结束设计模式要求为每个异步套接字 *** 作分配一个 IAsyncResult 对象。

socketasynceventargs类有一个Completed事件,一切和Async Socket有关的 *** 作结素后,都将调用该事件的处理函数。例如在上面的例子中,我们使用OnAcceptCompleted方法来处理Accept后的结果。通常我们使用此类执行异步套接字 *** 作的模式包含以下步骤:

分配一个新的 socketasynceventargs 上下文对象,或者从应用程序池中获取一个空闲的此类对象。 将该上下文对象的属性设置为要执行的 *** 作(例如,完成回调方法、数据缓冲区、缓冲区偏移量以及要传输的最大数据量)。 调用适当的套接字方法 (xxxAsync) 以启动异步 *** 作。 如果异步套接字方法 (xxxAsync) 返回 true,则在回调中查询上下文属性来获取完成状态。 如果异步套接字方法 (xxxAsync) 返回 false,则说明 *** 作是同步完成的。可以查询上下文属性来获取 *** 作结果。 将该上下文重用于另一个 *** 作,将它放回到应用程序池中,或者将它丢弃。

可以使用同一个socketasynceventargs来处理Accept(服务器)、Connect(客户端)、Send、Receive的结果,socketasynceventargs有一个Lastoperation的属性来标注该Completed是哪种 *** 作的结果:

//…………(e.Lastoperation == else if .Connect){    SocketAsyncoperation}//…………(e.Lastoperation == else if .Receive){    SocketAsyncoperation}//…………(e.Lastoperation == SocketError.Send){    
args.SetBuffer(new Byte[10240],10240);
}

当然,也可以为不同的 *** 作使用不同的socketasynceventargs对象。

可以在事件处理函数中通过观察SocketError属性来判断调用结果,当

e.socketError == 对于上述第二点,我们使用以下形式的策略文件:.Success

表明调用成功。

通过调用socketasynceventargs的SetBuffer方法,来设置需要发送的数据,或指定在接收数据时,的缓存数组。例如在上面例子里,我们为args设置了一个10240字节的数组,来存放接收到的数据:

<?

在Silverlight里使用Async Socket

在Silverlight里使用Async Socket,除了某些方法不支持外,大体上和完整版的.Net类似。不过,也有一些小小的限制:

网络应用程序可以连接到的端口范围必须在 4502-4534 范围内。这些是使用Socket从Silverlight应用程序进行连接所唯一允许使用的端口。如果连接的目标端口不在此端口范围内,则尝试连接时将会失败。 Silverlight 运行时中的安全策略系统要求必须先从网络资源下载一个策略文件,之后才允许网络连接访问该资源。源站点和跨域网络访问都因此而受到影响。

xml

version=1.0enCoding "=" utf-8?><"access-policy">    <cross-domain-access>        <policy>            <allow-from>                <domain uri=file:////>            </"allow-from" >            <grant-to>                <socket-resource port=4502-4506protocol"=" tcp/>            </"grant-to" >        </policy>    </cross-domain-access></access-policy>using using 

可以在服务器上架设一个Server服务,监听943接口。Silverlight通过Socket访问服务器资源时,首先连接到服务器地址的943端口,然后下载该策略文件。

封装好的AsyncclIEnt类

以下是我写的一个可在Silverlight中使用的Async Socket类,用于虚拟实验室里的Socket *** 作。和普通的Socket不同,该类在发送数据包时,在数据包头上添加4字节,作为数据包的长度;接收数据包时,同样的先读取前4字节,作为本次接收的长度。:

using System;using System.Collections.Generic;using System.linq;using System.Text;using System.Net.sockets;using System.IO;using System.Threading;namespace System.Net;public class System.ComponentModel;AsyncclIEnt Newinfosoft.Net.sockets{    INotifyPropertyChanged    #region : /// <summary>        /// {        当接收到数据时        Events        /// </summary>        public event AsyncConnectionEventHandler /// <summary>        /// 当数据发送完毕时        DataRecIEved;        /// </summary>        public event AsyncConnectionEventHandler /// <summary>        /// 当连接服务器成功时        DataSend;        /// </summary>        public event AsyncConnectionEventHandler /// <summary>        /// 当属性改变时(例如是否连接属性)        Connected;        /// </summary>        public event PropertyChangedEventHandler #endregion        /// <summary>        /// PropertyChanged;        用于存放接收时临时数据的内部类        /// 假设服务器发送来的数据格式为:        /// |数据长度n|数据本生        ///    4字节    n字节        /// </summary>        protected class StateObject        public byte/// <summary>            /// {            还有多少字节的数据没有接收            [] Buffer;            /// </summary>            public int public MemoryStream RemainSize = 0;            nullpublic Stream = int ;            new byteStateObject(if bufferSize)            {                Buffer = null[bufferSize];            }            ~StateObject()            {                /// <summary>        /// (Stream != 客户端Socket对象        )                {                    Stream.Close();                    Stream.dispose();                }            }        }        /// </summary>        public Socket getprivate setClIEnt { #region ; public ; }        socketasynceventargs 异步socketasynceventargs        getprivate setSendEventArgs { public ; socketasynceventargs ; }        getprivate setReceiveEventArgs { public ; socketasynceventargs ; }        getprivate setConnectEventArgs { #endregion        ; /// <summary>        /// ; }        读取或设置接收时的StateObject        /// </summary>        protected StateObject getsetState { /// <summary>        /// ; 发送锁,只有当前一个包中的数据全部发送完时,才允许发送下一个包        ; }        /// </summary>        protected object new objectprotected m_lockobject = ManualresetEvent ();        new ManualresetEventSendresetEvent = false#region (protected bool );        falseIsConnecting        /// <summary>        /// m_IsConnecting = 读取或设置是否连接到远程服务器,可用于绑定 *** 作        ;        /// </summary>        public bool get            return IsConnecting        {            set            {                if m_IsConnecting;            }            value{                value(m_IsConnecting != "IsConnecting")                {                    m_IsConnecting = #endregion        ;                    OnPropertyChanged(/// <summary>        /// );                }            }        }        通过指定的IPAddress和Port创建AsyncclIEnt,需要调用Connect方法连接        /// </summary>        /// <param name="bufferSize">接收缓存大小</param>        public int new AsyncclIEnt(StateObjectbufferSize)        {            State = new socketasynceventargs(bufferSize);            SendEventArgs = new socketasynceventargs();            ReceiveEventArgs = false/// <summary>        /// ();            ReceiveEventArgs.Completed += OnReceiveCompleted;            SendEventArgs.Completed += OnSendCompleted;            IsConnecting = 将已有的Socket包装为AsyncclIEnt对象,        ;        }        /// 如果Socket没有连接,则需要调用Connect方法        /// </summary>        /// <param name="socket">Socket对象</param>        /// <param name="bufferSize">接收缓存的大小</param>        public Socket int AsyncclIEnt(new socket,StateObjectbufferSize)        {            State = new socketasynceventargs(bufferSize);                        SendEventArgs = thisif ();            ReceiveEventArgs.Completed += OnReceiveCompleted;            SendEventArgs.Completed += OnSendCompleted;            null .ClIEnt = socket;            true(socket != else            && socket.Connected)            {                ReceiveEventArgs.SetBuffer(State.Buffer,State.Buffer.Length);                ClIEnt.ReceiveAsync(ReceiveEventArgs);                IsConnecting = false;            }            /// <summary>        /// {                IsConnecting = 连接        ;            }        }        /// </summary>        /// <param name="address">IP地址</param>        /// <param name="port">端口号</param>        public voID String int Connect(if address,nullport)        {            new (ClIEnt == Socket)            {                ClIEnt = AddressFamilyif (new .InterNetwork,175)">SocketType.Stream,175)">ProtocolType.Tcp);            }            socketasynceventargs(!ClIEnt.Connected)            {                ConnectEventArgs = EndPoint new ();                ConnectEventArgs.Completed += OnConnectComplete;                IPEndPointremoteEndPoint = IPAddress/// <summary>        /// (发送数据        .Parse(address),port);                ConnectEventArgs.RemoteEndPoint = remoteEndPoint;                ClIEnt.ConnectAsync(ConnectEventArgs);            }        }        /// </summary>        /// <param name="data">需要发送的数据</param>        public voID Byte/// <summary>        /// Send(发送数据,按照以下格式发送数据:        [] data)        {            Send(data,data.Length);        }        /// |数据长度n|需要发送的数据        ///    4字节        n字节        /// </summary>        /// <param name="data">需要发送的数据</param>        /// <param name="offset">需要发送数据的偏移量</param>        /// <param name="size">需要发送数据的长度</param>        public voID Byteint Send(int [] data,if offset,throw new size)        {            Exception(!IsConnecting)            {                "没有连接,无法发送数据!"lock (if );            }            null (m_lockobject)            {                return(data == //计算数据的长度,并转换成字节数组,作为本次发送的头部                || data.Length == 0)                    byte;                BitConverterByte[] length = new .GetBytes(size);                Byte[] buffer = ArrayArray[size + length.Length];                //设置发送Buffer                .copy(length,buffer,length.Length);                //等待发送成功的信息,只有收到该信息,才退出lock锁,                //这样,确保只有当前面得数据发送完后,才发送下一段数据                .copy(data,offset,length.Length,size);                protected voID SendEventArgs.SetBuffer(buffer,buffer.Length);                SendresetEvent.reset();                ClIEnt.SendAsync(SendEventArgs);                string SendresetEvent.WaitOne();            }        }        if OnPropertyChanged(nullpropertyname)        {            this(PropertyChanged != protected voID )            {                PropertyChanged(object ,175)">PropertyChangedEventArgs(propertyname));            }        }        if OnConnectComplete(SocketErrorsender,175)">socketasynceventargs e)        {            true(e.socketError == if .Success)            {                IsConnecting = null;                ReceiveEventArgs.SetBuffer(State.Buffer,State.Buffer.Length);                ClIEnt.ReceiveAsync(ReceiveEventArgs);                this(Connected != null)                {                    Connected(this,175)">AsyncConnectionEventArgs(else            ,false));                }            }            voID {                IsConnecting = object ;            }        }        //如果传输的数据量为0,则表示链接已经断开            OnSendCompleted(if sender,175)">socketasynceventargs e)        {            else            if (e.BytesTransferred == 0)            {                ClIEnt.Close();            }            null{                AsyncConnectionEventArgs (DataSend != new )                {                    AsyncConnectionEventArgsse = thisthis(e.Buffer,//通知数据发送完毕                );                    DataSend(/// <summary>        /// ,se);                }                接收数据处理函数        SendresetEvent.Set();            }        }        /// 1、将收到的数据包中的前4字节转换成Int32类型,作为本次数据包的长度。        /// 2、将这个值设置成StateObject的RemainSize。        /// 3、将数据包中剩下的数据写入StateObject的MemoryStream,并减少相应的RemainSize值。        /// 4、直到RemainSize=0时,表示这一段数据已经接收完毕,从而重复1,开始下一段数据包的接收        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        voID object //如果传输的数据量为0,则表示链接已经断开            OnReceiveCompleted(if sender,175)">socketasynceventargs e)        {            else            int (e.BytesTransferred == 0)            {                ClIEnt.Close();            }            while {                if position = 0;                int (position < e.BytesTransferred)                {                    if (State.RemainSize > 0)                    {                        if bytesToRead = State.RemainSize > e.BytesTransferred - position ?                            e.BytesTransferred - position : State.RemainSize;                        State.RemainSize -= bytesToRead;                        State.Stream.Write(State.Buffer,position,bytesToRead);                        position += bytesToRead;                        null(State.RemainSize == 0)                        {                            AsyncConnectionEventArgs (DataRecIEved != new )                            {                                AsyncConnectionEventArgsce =                                    thisthis(State.Stream.ToArray(),else                    );                                DataRecIEved(BitConverter,ce);                            }                            State.Stream.dispose();                        }                    }                    new {                        State.RemainSize = MemoryStream.ToInt32(State.Buffer,position);                        State.Stream = //重新设置数据缓存区                AsyncclIEnt (State.RemainSize);                        position += 4;                    }                }                new e.SetBuffer(State.Buffer,State.Buffer.Length);                ClIEnt.ReceiveAsync(e);            }        }    }}

使用方式如下:

AsyncclIEntclIEnt= "127.0.0.1"using (10240);clIEnt.Connected += OnClIEntConnected;clIEnt.DataRecIEved += OnClIEntDataRecIEved;clIEnt.Connect(using ,4503);
小节

本文介绍了在Silverlight中,如何使用Async Socket来连接服务器,以及如何编写跨域访问的配置文件。最后,给出了一个适用于Silverlight的类AsyncclIEnt,封装了Async Socket方法。注意,该类在每次发送数据时,需要在数据的前面发送该段数据的长度,因此,只能适用于采用类似方式编写的Server对象:

using System;using System.Collections.Generic;using System.linq;using System.Text;using System.Net.sockets;using System.Net;namespace System.Threading;/// <summary>    /// System.IO;ConnectionServer在.Net 2.0 sp1上的实现    Newinfosoft.Net.sockets{    /// </summary>    public class AsyncServer    #region /// <summary>        /// {        接收到数据        events        /// </summary>        public event AsyncConnectionEventHandler public event AsyncConnectionEventHandler DataRecIEved;        /// <summary>        /// 远程Socket连接        DataSend;        /// </summary>        public event AsyncConnectionEventHandler /// <summary>        /// 开始监听端口        RemoteSocketAccept;        /// </summary>        public event EventHandler /// <summary>        /// 停止监听端口        Started;        /// </summary>        public event EventHandler #endregion        protected class StateObject        Stoped;        public Socket {            nullpublic byteClIEntSocket = public int ;            public [] Buffer;            MemoryStream RemainSize = 0;            nullpublic Stream = int ;            new byteStateObject(/// <summary>        /// bufferSize)            {                Buffer = 读取TCP监听服务        [bufferSize];            }            ~StateObject()            {                Stream.Close();                Stream.dispose();            }        }        /// </summary>        public Socket getprivate setServer        {            /// <summary>        /// ;            读取当前服务的端口号        ;        }        /// </summary>        public int getprivate setPort        {            /// <summary>        /// ;            读取或设置是否正在监听端口        ;        }        /// </summary>        public bool getsetIsListening        {            /// <summary>        /// ;            读取或设置缓存大小        ;        }        /// </summary>        public int getsetBufferSize        {            public ;            socketasynceventargs ;        }        getsetAcceptEventArgs { #region ; /// <summary>        /// ; }        构造函数        构造函数        /// </summary>        /// <param name="port">监听端口</param>        public int thisAsyncServer(/// <summary>        /// port)            : 构造函数        (port,20480)        {        }        /// </summary>        /// <param name="port">监听端口</param>        /// <param name="bufferSize">缓存大小</param>        public int int AsyncServer(#endregion        public voID port,try            bufferSize)        {            Port = port;            BufferSize = bufferSize;        }        if Start()        {            null{                IPEndPoint (Server == new )                {                    IPAddresslocalEP = new Socket.Any,Port);                    Server = inttrue(localEP.AddressFamily,175)">ProtocolType.Tcp);                    Server.Bind(localEP);                }                Server.Listen(if .MaxValue);                IsListening = null;                this(Started != new )                {                    Started(socketasynceventargs,175)">EventArgs());                }                AcceptEventArgs = catch SocketException ();                AcceptEventArgs.Completed += OnAcceptCompleted;                Server.AcceptAsync(AcceptEventArgs);            }            throw (public voID ex)            {                falseex;            }        }        if Stop()        {            IsListening = null;            null(Server != if )            {                Server.Close();                Server = null;                this(Stoped != #region )                {                    Stoped(protected voID ,175)">EventArgs());                }            }        }        object Accept        if OnAcceptCompleted(nullsender,175)">socketasynceventargs e)        {            AsyncclIEnt (e.AcceptSocket.RemoteEndPoint != new )            {                AsyncclIEntclIEnt = if null(e.AcceptSocket,BufferSize);                clIEnt.DataRecIEved += (s2,e2) =>                {                    this(DataRecIEved != if )                    {                        DataRecIEved(null,e2);                    }                };                clIEnt.DataSend += (s2,e2) =>                {                    this(DataSend != //抛出远程Socket连接事件                )                    {                        DataSend(if ,e2);                    }                };                nullthis(RemoteSocketAccept != null)                {                    RemoteSocketAccept(#endregion    ,clIEnt));                }                e.AcceptSocket = ;                Server.AcceptAsync(AcceptEventArgs);            }        }        }}
 总结

以上是内存溢出为你收集整理的Silverlight下的Socket通讯全部内容,希望文章能够帮你解决Silverlight下的Socket通讯所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1013364.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-22
下一篇 2022-05-22

发表评论

登录后才能评论

评论列表(0条)

保存