2011-04-10 29 views

回答

2

Networking in Silverlight有很多限制,主要與Silverlight在瀏覽器中的沙箱中運行有關(例如,跨域策略,端口限制等),部分可以通過使用OOB應用程序來解決安全模型)。

但是,Silverlight爲Sockets提供了一些支持,並且在那裏有一些高級客戶端實現,如this one

這些可能是開始構建自己的端口的一個很好的基礎,因爲我認爲.NET 4運行時許可證不包括分叉源代碼的權利,甚至不會將它們移植到Silverlight。

+0

感謝但注意到第一個問題。他們爲什麼失蹤? – 2011-04-11 09:10:31

+0

我想WCF/WebService,HttpWebRequest,WebClient的集成在第一個版本中似乎是「足夠」的,而低級聯網後來被開發人員要求時,限制變得更加令人沮喪。但我想只有Silverlight開發團隊將對你的問題的這一部分有100%的答案;) – jCoder 2011-04-11 16:09:49

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 
    } 
}