2012-08-05 275 views
4

我有TCP套接字服务器,并希望为它制作异步的Silverlight客户端,但是我找不到任何有用的信息。确切地说,我需要三个步骤:连接,发送和接收。Silverlight中的异步套接字连接

不需要它非常详细,只是想法如何构建它至少连接到服务器。

顺便说一句,我使用Silverlight 5

+1

也许这会帮助你http://channel9.msdn.com/Blogs/mtaulty/Silverlight-Beta-4-Networking-Part-8-TCP-Sockets – 2012-08-12 20:13:33

+0

谢谢! :))我做了一切像在视频中显示,一切正常工作! :))没有你没有找到这个! :P – 2012-08-12 22:48:33

+0

如果您将此链接发布为答案,我会批准它作为奖励。因为根据我的理解,我无法奖励自己的奖励,否则100个声望就会失去。我真的认为你应得的:)并感谢你编辑语法错误。我很感激。 – 2012-08-13 12:44:03

回答

9

非常感谢你,卡雷尔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

OR

  • 跨域策略文件托管在HTTP服务器(80端口)。

如果您选择使用插槽服务器,这里的工作示例源代码:从here采取

样品并说那里

策略服务器< ...>必须在端口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套接字服务器示例,只需询问并给我链接问题!我有一个用异步等待关键字构建的,尽可能简单。

祝你好运!

3

Mike Taulty制作了一个视频,介绍了Silverlight 4的网络,套接字被讨论为here

+0

现在让我给我奖励自己,但我真的很感谢你的帮助,所以我仍然给你赏金。再次感谢! :) – 2012-08-14 13:42:20