为什么Silverlight中缺少TCPClient和NetworkStream?是否有任何已知的TCPClient和NetworkStream端口到Silverlight?如果没有,我是否可以将源代码从.NET 4运行时复制到我自己的库中?如果没有,我如何开始将这些类移植到Silverlight?
Networking in Silverlight有一些限制,主要与Silverlight在浏览器中的沙箱中运行(例如跨域策略,端口限制等)有关,这可以部分通过使用具有宽松安全模型的OOB应用程序来解决 .
但是,Silverlight为Sockets提供了一些支持,并且有一些高级客户端实现,如this one .
这些可能是开始构建自己的端口的良好基础,因为我认为.NET 4运行时许可证不包括fork源代码的权限,甚至不包括将它们移植到Silverlight .
我知道这个问题很老,但对我来说非常有用 . 谢谢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 } }
2 回答
Networking in Silverlight有一些限制,主要与Silverlight在浏览器中的沙箱中运行(例如跨域策略,端口限制等)有关,这可以部分通过使用具有宽松安全模型的OOB应用程序来解决 .
但是,Silverlight为Sockets提供了一些支持,并且有一些高级客户端实现,如this one .
这些可能是开始构建自己的端口的良好基础,因为我认为.NET 4运行时许可证不包括fork源代码的权限,甚至不包括将它们移植到Silverlight .
我知道这个问题很老,但对我来说非常有用 . 谢谢jCoder,我实际上是根据你的链接文章创建了一个解决方案 . http://weblogs.asp.net/mschwarz/archive/2008/03/07/silverlight-2-and-sockets.aspx
我做了一些改变 . 最值得注意的是,TcpClient中存在内存泄漏,我通过处理在发送和接收中创建的ScoketAsyncEventArgs来解决 . 这里可能有更好的方法,但它有效,所以我不再寻找了 . 如果没有这个,似乎由于订阅事件而保留了引用 . 公开征求意见 .
我只使用了BinaryReader和BinaryWriter,你的里程可能因其他读者而异 .