Как перенести TCPClient и NetworkStream в Silverlight? - PullRequest
1 голос
/ 10 апреля 2011

Почему TCPClient и NetworkStream отсутствуют в Silverlight?
Существуют ли какие-либо известные порты TCPClient и NetworkStream для Silverlight?
Если нет, могу ли я скопировать исходный код из среды выполнения .NET 4 в мою собственную библиотеку?
Если нет, то как мне начать перенос этих классов в Silverlight?

Ответы [ 2 ]

2 голосов
/ 10 апреля 2011

Существуют некоторые ограничения на Работа в сети в Silverlight , в основном связанная с тем, что Silverlight запускается в песочнице в браузере (например, междоменная политика, ограничения портов и другие, которые могут быть частично решены).с помощью приложений OOB с моделью ослабленной безопасности).

Однако Silverlight обеспечивает некоторую поддержку сокетов , и существует несколько высокоуровневых клиентских реализаций, таких как эта.

Возможно, это хорошая основа для создания собственных портов, так как я полагаю, что лицензия времени выполнения .NET 4 не включает в себя право на разветвление исходных кодов, даже на перенос их в Silverlight.

1 голос
/ 11 июля 2014

Я знаю, что этот вопрос старый, но он был очень полезен для меня. Спасибо jCoder, я на самом деле создал решение на основе вашей связанной статьи. http://weblogs.asp.net/mschwarz/archive/2008/03/07/silverlight-2-and-sockets.aspx

Я сделал несколько изменений. В частности, в том TcpClient есть утечка памяти, которую я решил, избавившись от ScoketAsyncEventArgs, созданных в send и receive. Может быть, есть и лучший способ, но это сработало, и я перестал искать. Без этого кажется, что ссылка сохраняется из-за подписки на событие. Открыта для предложений.

Я использовал это только с 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
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...