玄铁剑

成功的途径:抄,创造,研究,发明...
posts - 128, comments - 42, trackbacks - 0, articles - 174

Silverlight 2 and System.Net.Sockets.Socket

Posted on 2008-03-16 21:34 玄铁剑 阅读(1412) 评论(3)  编辑 收藏 引用 所属分类: Silverlight

Silverlight 2 and System.Net.Sockets.Socket
The new beta of Silverlight 2 introduces Sockets. The security model enforced by the System.Net.Sockets namespace in Silverlight 2 allows for a connection only back to the site or host of origin. So Silverlight 2 applications will be allowed to connect only to the host from which they were downloaded.

As the Web browser doesn't have a property of the IP address (as you may expect using sockets) there is a new endpoint class, the DnsEndPoint. To create a new instance of DnsEndPoint you have to specify the host name (as string e.g. from Application.Current.Host.Source.DnsSafeHost) and the port address.

string host = "mydomain.com";
int port = 80;
DnsEndPoint endPoint = new DnsEndPoint(host, port);All methods of the Socket class to connect, send or receive have to be used asynchronous. I've created a small helper class that wraps all the asynchronous operations. You can download the C# source here.

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace Networking
{
    internal sealed class SocketClient : IDisposable
    {
        private const int Receive = 1;
        private const int Send = 0;

        private bool isConnected = false;

        private Socket socket;
        private DnsEndPoint endPoint;

        private static AutoResetEvent autoEvent = new AutoResetEvent(false);
        private static AutoResetEvent[] autoSendReceiveEvents = new AutoResetEvent[]
                {
                        new AutoResetEvent(false),
                        new AutoResetEvent(false)
                };

        internal SocketClient(string host, int port)
        {
            endPoint = new DnsEndPoint(host, port);
            socket = new Socket(AddressFamily.InterNetwork
                        /* hostEndPoint.AddressFamily */,
                        SocketType.Stream, ProtocolType.Tcp);
        }

        internal void Connect()
        {
            SocketAsyncEventArgs args = new SocketAsyncEventArgs();

            args.UserToken = socket;
            args.RemoteEndPoint = endPoint;
            args.Completed += new EventHandler<SocketAsyncEventArgs>(OnConnect);

            socket.ConnectAsync(args);
            autoEvent.WaitOne();

            if (args.SocketError != SocketError.Success)
                throw new SocketException((int)args.SocketError);
        }

        internal void Disconnect()
        {
            socket.Close();
        }

        #region Events

        private void OnConnect(object sender, SocketAsyncEventArgs e)
        {
            autoEvent.Set();
            isConnected = (e.SocketError == SocketError.Success);
        }

        private void OnReceive(object sender, SocketAsyncEventArgs e)
        {
            autoSendReceiveEvents[Send].Set();
        }

        private void OnSend(object sender, SocketAsyncEventArgs e)
        {
            autoSendReceiveEvents[Receive].Set();

            if (e.SocketError == SocketError.Success)
            {
                if (e.LastOperation == SocketAsyncOperation.Send)
                {
                    // Prepare receiving.
                    Socket s = e.UserToken as Socket;

                    byte[] response = new byte[255];
                    e.SetBuffer(response, 0, response.Length);
                    e.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceive);
                    s.ReceiveAsync(e);
                }
            }
            else
            {
                ProcessError(e);
            }
        }

        #endregion

        private void ProcessError(SocketAsyncEventArgs e)
        {
            Socket s = e.UserToken as Socket;
            if (s.Connected)
            {
                try
                {
                    s.Shutdown(SocketShutdown.Both);
                }
                catch (Exception)
                {
                }
                finally
                {
                    if (s.Connected)
                        s.Close();
                }
            }

            throw new SocketException((int)e.SocketError);
        }

        internal String SendReceive(string message)
        {
            if (isConnected)
            {
                Byte[] bytes = Encoding.UTF8.GetBytes(message);

                SocketAsyncEventArgs args = new SocketAsyncEventArgs();
                args.SetBuffer(bytes, 0, bytes.Length);
                args.UserToken = socket;
                args.RemoteEndPoint = endPoint;
                args.Completed += new EventHandler<SocketAsyncEventArgs>(OnSend);

                socket.SendAsync(args);

                AutoResetEvent.WaitAll(autoSendReceiveEvents);

                return Encoding.UTF8.GetString(args.Buffer, args.Offset, args.BytesTransferred);
            }
            else
                throw new SocketException((int)SocketError.NotConnected);
        }

        #region IDisposable Members

        public void Dispose()
        {
            autoEvent.Close();
            autoSendReceiveEvents[Send].Close();
            autoSendReceiveEvents[Receive].Close();
            if (socket.Connected)
                socket.Close();
        }

        #endregion
    }
}

Feedback

# 请教关于SL 2.1 中socket开发问题  回复  更多评论   

2008-05-07 09:55 by 老谷
hi,看了你的 Silverlight 2 and System.Net.Sockets.Socket
有不少疑问,SL客户端只能和web服务器连接,那web服务器上的socket server应该如何开发??

# re: Silverlight 2 and System.Net.Sockets.Socket [未登录]  回复  更多评论   

2008-05-07 21:55 by martin
可以采用WCF来撰写服务器端...
string host = "mydomain.com";
int port = 80;
DnsEndPoint endPoint = new DnsEndPoint(host, port);

# re: Silverlight 2 and System.Net.Sockets.Socket   回复  更多评论   

2008-11-18 10:54 by sunrenpeng
帮忙给出socket 客户端 和wcf服务端通讯的列子
用于传输文件
只有注册用户登录后才能发表评论。