1

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

4

2 回答 2

2

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

但是,Silverlight 提供了一些对Sockets的支持,并且有一些高级客户端实现,比如这个

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

于 2011-04-10T13:25:42.757 回答
1

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

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

我只将它与 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
    }
}
于 2014-07-11T17:51:05.123 回答