私は TCP ソケット サーバーを持っており、そのために非同期の Silverlight クライアントを作成したいと考えていますが、それに関する有用な情報が見つかりません。正確には、接続、送信、受信の 3 つの手順が必要です。
非常に詳細である必要はありません。少なくともサーバーに接続するためにそれを構築する方法を考えてください。
ちなみにSilverlight5を使っています。
私は TCP ソケット サーバーを持っており、そのために非同期の Silverlight クライアントを作成したいと考えていますが、それに関する有用な情報が見つかりません。正確には、接続、送信、受信の 3 つの手順が必要です。
非常に詳細である必要はありません。少なくともサーバーに接続するためにそれを構築する方法を考えてください。
ちなみにSilverlight5を使っています。
Karel Frajtak、Silverlightのソケットに関するビデオへのリンクをありがとうございました。そのビデオチュートリアルではすべてが示され、説明されているので、Silverlightのソケットが必要なすべての人にそれを視聴することをお勧めします!これが私が必要とした解決策であり、何が何をするのかについての説明と私のコメントがあります:
すべての接続アクションは別のクラスSocketConnectionによって処理されると思います。
public class MessageEventArgs : EventArgs
{
public string Message { get; set; }
}
public class SocketConnection
{
/// <summary>
/// Event handler shot when message is received
/// </summary>
public event EventHandler<MessageEventArgs> MessageReceived;
/// <summary>
/// Socket used for connection to the server, sending and receiving data
/// </summary>
Socket socket;
/// <summary>
/// Default buffer size that should be used with the same value in both server and client
/// </summary>
int bufferSize = 128;
/// <summary>
/// Buffer used to store bytes received
/// </summary>
byte[] buffer;
/// <summary>
/// Bytes received in current receiving operation
/// </summary>
int bytesReceived;
public SocketConnection(string host = "localhost", int port = 4502)
{
// Initializing buffer for receiving data
buffer = new byte[bufferSize];
// Initializing socket to connect to the server with default parameters
// *** If you need IPv6, set the AddressFamily.InterNetworkV6 ***
// *** Silverlight supports only Stream or Unknown socket types (Silverlight 5) ***
// *** The only defined protocol supported by Silverlight is TCP.
// Others can be only Unknown or Unspecified (Silverlight 5)***
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Socket args that are needed for connection
SocketAsyncEventArgs args = new SocketAsyncEventArgs()
{
// Server IP and port
RemoteEndPoint = new DnsEndPoint(host, port),
// If policy server is hosted as TCP socket, this has to be set to SocketClientAccessPolicyProtocol.Tcp
// If policy is stored in HTTP server, this has to be set SocketClientAccessPolicyProtocol.Http
SocketClientAccessPolicyProtocol = SocketClientAccessPolicyProtocol.Tcp
};
// Set the event handler for completed connection (nomatter if it is successful or not)
args.Completed += OnConnected;
// Start connecting to the server asynchronously
socket.ConnectAsync(args);
}
/// <summary>
/// Even handler shot when socket connection is completed
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void OnConnected(object sender, SocketAsyncEventArgs e)
{
// If the connection is not successful, set socket object to null
if (e.SocketError != SocketError.Success)
{
if (e.SocketError == SocketError.AccessDenied)
{
// Policy server is not running or cannot be reached
throw new SocketException((int)SocketError.AccessDenied);
}
socket = null;
}
// Begin receiving data otherwise
else
{
BeginRead();
}
}
/// <summary>
/// Method for receiving data from the server
/// </summary>
private void BeginRead()
{
// Receive data only if socket is connected
if (socket != null && socket.Connected)
{
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
// Store the received buffer in a class variable
args.SetBuffer(buffer, bytesReceived, buffer.Length - bytesReceived);
// Set the event handler for received data
args.Completed += OnReceived;
// Start receiving data asynchronously
socket.ReceiveAsync(args);
}
}
/// <summary>
/// Event handler shot when data is received from the server
/// </summary>
void OnReceived(object sender, SocketAsyncEventArgs e)
{
// Make sure that receiving was successful
if (e.SocketError == SocketError.Success)
{
// Increase the count of received bytes in the current receiving operation
bytesReceived += e.BytesTransferred;
}
// If the receiving was unsuccessful, throw an exception
else
{
throw new SocketException();
}
// Check if the buffer is already full
if (bytesReceived == buffer.Length)
{
// If the buffer is full, decode the string received from bytes
// *** This should be your object deserialization, if you use anything but string ***
string text = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
// If the event was set from somewhere, shoot it
// *** In most cases event is set from UI thread to handle the
// received string or object and show the result to user ***
if (MessageReceived != null)
{
// Shoot the event, if it's set
MessageReceived(this, new MessageEventArgs()
{
Message = text
});
}
// Set the bytes received count to 0, for other data receiving event to fill the buffer from begining
bytesReceived = 0;
}
// Begin the data receiving again
BeginRead();
}
/// <summary>
/// Sample method to send data to the server
/// </summary>
/// <param name="text">Text you would like the server to receive</param>
public void SendText(string text)
{
// Check if the socket is connected to the server
if (socket != null && socket.Connected)
{
// Encode the string to be sent to bytes
// *** This is where your object serialization should be done ***
byte[] buffer = Encoding.UTF8.GetBytes(text);
// Check if the buffer is not empty
if (buffer.Length != 0)
{
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
// Set the buffer to be sent
args.SetBuffer(buffer, 0, buffer.Length);
// Start sending buffer to the server asynchronously
socket.SendAsync(args);
}
}
}
}
Silverlightでのソケット接続を成功させるには、次のことが必要です。
また
ソケットサーバーを使用する場合は、次のサンプルソースコードを使用してください。
ここから取られたサンプルとそれはそこにそれを言います
ポリシーサーバー<...>はポート943で実行する必要があります
記事が古すぎるという理由だけで、HTTPサーバーでホストする可能性については何も述べていません。
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace PolicyServer
{
// Encapsulate and manage state for a single connection from a client
class PolicyConnection
{
private Socket _connection;
private byte[] _buffer; // buffer to receive the request from the client
private int _received;
private byte[] _policy; // the policy to return to the client
// the request that we're expecting from the client
private static string _policyRequestString = "<policy-file-request/>";
public PolicyConnection(Socket client, byte[] policy)
{
_connection = client;
_policy = policy;
_buffer = new byte[_policyRequestString.Length];
_received = 0;
try
{
// receive the request from the client
_connection.BeginReceive(_buffer, 0, _policyRequestString.Length, SocketFlags.None,
new AsyncCallback(OnReceive), null);
}
catch (SocketException)
{
_connection.Close();
}
}
// Called when we receive data from the client
private void OnReceive(IAsyncResult res)
{
try
{
_received += _connection.EndReceive(res);
// if we haven't gotten enough for a full request yet, receive again
if (_received < _policyRequestString.Length)
{
_connection.BeginReceive(_buffer, _received, _policyRequestString.Length - _received,
SocketFlags.None, new AsyncCallback(OnReceive), null);
return;
}
// make sure the request is valid
string request = System.Text.Encoding.UTF8.GetString(_buffer, 0, _received);
if (StringComparer.InvariantCultureIgnoreCase.Compare(request, _policyRequestString) != 0)
{
_connection.Close();
return;
}
// send the policy
Console.Write("Sending policy...\n");
_connection.BeginSend(_policy, 0, _policy.Length, SocketFlags.None,
new AsyncCallback(OnSend), null);
}
catch (SocketException)
{
_connection.Close();
}
}
// called after sending the policy to the client; close the connection.
public void OnSend(IAsyncResult res)
{
try
{
_connection.EndSend(res);
}
finally
{
_connection.Close();
}
}
}
// Listens for connections on port 943 and dispatches requests to a PolicyConnection
class PolicyServer
{
private Socket _listener;
private byte[] _policy;
// pass in the path of an XML file containing the socket policy
public PolicyServer(string policyFilePath)
{
// Load the policy file
FileStream policyStream = new FileStream(policyFilePath, FileMode.Open);
_policy = new byte[policyStream.Length];
policyStream.Read(_policy, 0, _policy.Length);
policyStream.Close();
// Create the Listening Socket
_listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp);
_listener.SetSocketOption(SocketOptionLevel.Tcp, (SocketOptionName)
SocketOptionName.NoDelay, 0);
_listener.Bind(new IPEndPoint(IPAddress.Any, 943));
_listener.Listen(10);
_listener.BeginAccept(new AsyncCallback(OnConnection), null);
}
// Called when we receive a connection from a client
public void OnConnection(IAsyncResult res)
{
Socket client = null;
try
{
client = _listener.EndAccept(res);
}
catch (SocketException)
{
return;
}
// handle this policy request with a PolicyConnection
PolicyConnection pc = new PolicyConnection(client, _policy);
// look for more connections
_listener.BeginAccept(new AsyncCallback(OnConnection), null);
}
public void Close()
{
_listener.Close();
}
}
public class Program
{
static void Main()
{
Console.Write("Starting...\n");
PolicyServer ps =
new PolicyServer(@".\clientaccesspolicy.xml");
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
}
}
}
それについてです。最初にクロスドメインポリシーサーバーを 実行し、次にクライアントを実行して、接続が成功することを確認します。
非同期のWPFソケットサーバーのサンプルが必要な場合は、質問して質問へのリンクを教えてください。できるだけシンプルにするために、async-awaitキーワードでビルドしたものがあります。
すべてで頑張ってください!
Mike Taultyは、Silverlight 4ネットワーキングの紹介を含むビデオを作成しました。ソケットについては、ここで説明します。