首页 文章

如何将TCPClient和NetworkStream移植到Silverlight?

提问于
浏览
1

为什么Silverlight中缺少TCPClient和NetworkStream?
是否有任何已知的TCPClient和NetworkStream端口到Silverlight?
如果没有,我是否可以将源代码从.NET 4运行时复制到我自己的库中?
如果没有,我如何开始将这些类移植到Silverlight?

2 回答

  • 1

    Networking in Silverlight有一些限制,主要与Silverlight在浏览器中的沙箱中运行(例如跨域策略,端口限制等)有关,这可以部分通过使用具有宽松安全模型的OOB应用程序来解决 .

    但是,Silverlight为Sockets提供了一些支持,并且有一些高级客户端实现,如this one .

    这些可能是开始构建自己的端口的良好基础,因为我认为.NET 4运行时许可证不包括fork源代码的权限,甚至不包括将它们移植到Silverlight .

  • 2

    我知道这个问题很老,但对我来说非常有用 . 谢谢jCoder,我实际上是根据你的链接文章创建了一个解决方案 . http://weblogs.asp.net/mschwarz/archive/2008/03/07/silverlight-2-and-sockets.aspx

    我做了一些改变 . 最值得注意的是,TcpClient中存在内存泄漏,我通过处理在发送和接收中创建的ScoketAsyncEventArgs来解决 . 这里可能有更好的方法,但它有效,所以我不再寻找了 . 如果没有这个,似乎由于订阅事件而保留了引用 . 公开征求意见 .

    我只使用了BinaryReader和BinaryWriter,你的里程可能因其他读者而异 .

    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;
    
    namespace IBApi
    {
        public class TcpClientSl
        {
          private const int Receive = 1;
          private const int Send = 0;
    
          private bool isConnected = false;
    
          private Socket socket;
          private DnsEndPoint endPoint;
          public NotifyStream socketStream;
    
          private static AutoResetEvent autoEvent = new AutoResetEvent(false);
          private static AutoResetEvent autoSendEvent = new AutoResetEvent(false);
          private static AutoResetEvent autoReceiveEvent = new AutoResetEvent(false);
    
          NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
    
            public TcpClientSl(string host, int port)
            {
              logger.Trace("TcpClientSl(string {0}, int {1})", host, port);
    
              endPoint = new DnsEndPoint(host, port, AddressFamily.InterNetwork);
    
              socket = new Socket(AddressFamily.InterNetwork 
                          /* hostEndPoint.AddressFamily */, 
                          SocketType.Stream, ProtocolType.Tcp);
              socketStream = new NotifyStream();
              socketStream.OnRead = ReadDelegate;
              socketStream.OnWrite = WriteDelegate;
            }
    
            int ReadDelegate (byte[] buffer, int offset, int count)
            {
              //logger.Trace("ReadDelegate (byte[] buffer, int {0}, int {1})", offset, count);
                // Prepare receiving.
                SocketAsyncEventArgs args = new SocketAsyncEventArgs();
                args.SetBuffer(buffer, 0, buffer.Length);
                args.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceive);
                socket.ReceiveAsync(args);
                if (!autoReceiveEvent.WaitOne(TimeSpan.FromMinutes(5)))
                {
                  logger.Error("Receive Timeout");
                  //this.Disconnect();
                }
                args.Dispose();
                return args.BytesTransferred;
            }
    
            void WriteDelegate(byte[] buffer, int offset, int count)
            {
              //logger.Trace("WriteDelegate(byte[] buffer, int {0}, int {1})", offset, count);
              if (isConnected && socket.Connected)
              {
                  SocketAsyncEventArgs args = new SocketAsyncEventArgs();
                  args.SetBuffer(buffer, offset, count);
                  args.UserToken = socket;
                  args.RemoteEndPoint = endPoint;
                  args.Completed += new EventHandler<SocketAsyncEventArgs>(OnSend);
    
                  socket.SendAsync(args);
    
                  if (!autoSendEvent.WaitOne(TimeSpan.FromMinutes(1)))
                  {
                    logger.Error("Send Timeout");
                    //this.Disconnect();
                  }
                  args.Dispose();
              }
              else
                  throw new SocketException((int)SocketError.NotConnected);
            }
    
            public void Connect()
            {
    
              logger.Trace("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);
            }
    
            public void Disconnect()
            {
              logger.Trace("Disconnect()");
              socket.Close();
            }
    
            #region Events
    
            private void OnConnect(object sender, SocketAsyncEventArgs e)
            {
              logger.Trace("OnConnect");
              autoEvent.Set();
              isConnected = (e.SocketError == SocketError.Success);
            }
    
            private void OnReceive(object sender, SocketAsyncEventArgs e)
            {
              //logger.Trace("OnReceive {0} bytes", e.BytesTransferred);
              if (e.BytesTransferred > 0)
              {
                autoReceiveEvent.Set();
              }
            }
    
            private void OnSend(object sender, SocketAsyncEventArgs e)
            {
              //logger.Trace("OnSend Bytes={0}", e.BytesTransferred);
    
              autoSendEvent.Set();
    
              if (e.SocketError == SocketError.Success)
              {
                  if (e.LastOperation == SocketAsyncOperation.Send)
                  {
                  }
              }
              else
              {
                  ProcessError(e);
              }
            }
    
            #endregion
    
            private void ProcessError(SocketAsyncEventArgs e)
            {
              logger.Trace("ProcessError");
              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);
            }
    
            #region IDisposable Members
    
            public void Dispose()
            {
              logger.Trace("Dispose");
              autoEvent.Close();
              autoSendEvent.Close();
              autoReceiveEvent.Close();
              if (socket.Connected)
                  socket.Close();
            }
    
            #endregion
        }
    }
    

相关问题