TCPClient と NetworkStream が Silverlight にないのはなぜですか?
TCPClient と NetworkStream の Silverlight への既知のポートはありますか?
存在しない場合、ソース コードを .NET 4 ランタイムから自分のライブラリにコピーすることはできますか?
そうでない場合、これらのクラスを Silverlight に移植するにはどうすればよいですか?
2 に答える
Silverlight のネットワークにはかなりの制限があります。主に、Silverlight がブラウザーのサンドボックスで実行されるという事実に関連しています (たとえば、クロス ドメイン ポリシー、ポート制限など、緩和されたセキュリティ モデルで OOB アプリケーションを使用することで部分的に解決できます)。 )。
ただし、Silverlight はSocketsのサポートを提供しており、このような高レベルのクライアント実装がいくつかあります。
.NET 4 ランタイム ライセンスには、ソース コードを fork する権利は含まれておらず、Silverlight に移植する権利さえ含まれていないため、これらは独自のポートの構築を開始するための優れた基盤となる可能性があります。
この質問は古いことは知っていますが、私にとっては非常に役に立ちました。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
}
}