socket communication under SilverlightCategory: Silverlight| WPF 2012-06-17 22:15 1513 People read review (1) Bookmark report Socket Silverlight Server byte string button
This article copyright belongs to the blog Park Cheng Xingliang All, if reproduced, please strictly according to the following way to indicate the original author and source, to show respect.
Author: Cheng Xingliang
Source: http://www.cnblogs.com/chengxingliang/archive/2012/05/24/2515100.html
In Silverlight, you can only use ports between 4502-4534 for data transfer, and Silverlight clients will automatically send a "<policy-file-request/>" to the server side of Port 943. Statement request, and then the server-side 943 port sends back the following files to license the socket communication.
<?xml version= "1.0" encoding= "Utf-8"?>
<access-policy>
<cross-domain-access>
< policy>
<allow-from>
<domain uri= "*"/>
</allow-from>
<grant-to>
<socket-resource port= "4502-4534" protocol= "tcp"/>
</grant-to>
</policy>
</ Cross-domain-access>
</access-policy>
A. Now let's look at the server-side code, which is mainly divided into the policy response steps and the service response steps.
policy Step one : Start listening on port 943 if there is a need for a security policy file request
policy Step Two : If the client request is <POLICY-FILE-REQUEST/>, send the security policy file as bytes to the client
Service Step One : Start the server side, listen to port 4525, whether there is a socket dialog request
Service Step Two : If there is a connection requested by the client, send a message informing the client
The code is as follows:
Class Program {static void Main (string[] args) {//Policy step one: start listening on port 943 if there is a need for a security policy file request
Thread access = new Thread (new ThreadStart (Accessthread)); Access.
Start ();
Service Step One: Start the server side, listen to port 4525, whether there is a socket dialog request thread Server = new Thread (new ThreadStart (Serverthread)); Server.
Start (); }//Policy request listener static void Accessthread () {//Get Socket server socket for 943 port listening Socke
t = getsocketserver (943); while (true) {socket new_access = socket.
Accept ();
String clientpolicystring = "<policy-file-request/>";
byte[] requestbytes = new Byte[clientpolicystring.length]; New_access.
Receive (requestbytes); String requeststring = System.Text.Encoding.UTF8.GetString (requestbytes, 0, Requestbytes.
Length);
if (requeststring = = clientpolicystring) {//Policy step two: If the client request is <POLICY-FILE-REQUEST/>, the security policy file is sent as bytes to the client byte[] Acc
Essbytes = Getpolicytoclient (); New_access. Send (Accessbytes, Accessbytes.
Length, Socketflags.none); New_access.
Close ();
} thread.sleep (100); }} static void Serverthread () {//Get 4525 Port listener socket SOCKET SOCKET = G
Etsocketserver (4525); while (true) {socket _socket = socket.
Accept ();
Service Step Two: If there is a client-requested connection, send a message informing the client byte[] b2 = new byte[1024]; _socket.
Receive (B2); Console.WriteLine (Encoding.UTF8.GetString (B2).
Replace ("n", ""));
String recstring = "I have received the message"; _socket.
Send (Encoding.UTF8.GetBytes (recstring)); _socket.
Close ();
Thread.Sleep (100);
}
} Establish socket server-side static socket getsocketserver (int serverport) {Socket socket = new Socke based on port
T (AddressFamily.InterNetwork, SocketType.Stream, protocoltype.tcp); Socket.
Bind (New IPEndPoint (Ipaddress.any, ServerPort)); Socket.
Listen (40);
return socket; }//Get security policy file byte[] static byte[] Getpolicytoclient () {String path = Environment.curr
Entdirectory.replace ("\\bin\\Debug", "" ");
FileStream fs = new FileStream (path+ @ "\clientaccesspolicy.xml", FileMode.Open); int length = (int) fs.
Length;
byte[] bytes = new Byte[length]; Fs.
Read (bytes, 0, length); Fs.
Close ();
return bytes; }
}
B. Next we look at the client operation, divided into the following steps:
client Step One : initiates a server connection request.
client Step Two : The connection server succeeds, puts the data that needs to be sent into the buffer, and then asynchronously sends a message request to the server
Client Step three : The message is sent successfully, a new buffer instance is set up, and the message returned by the asynchronous receive server is initiated
Client Step four : Get the message returned to the server, close the socket
The client CS code is as follows:
Public partial class Mainpage:usercontrol {public MainPage () {InitializeComponent (
);
} System.Net.Sockets.Socket Socket; private void Button1_Click (object sender, RoutedEventArgs e) {byte[] userbytes = Encoding.UTF8.GetByt
ES (This.tbInput.Text);
Socket = new System.Net.Sockets.Socket (AddressFamily.InterNetwork, SocketType.Stream, protocoltype.tcp);
SocketAsyncEventArgs Socketargs = new SocketAsyncEventArgs ();
Socketargs.remoteendpoint = new Dnsendpoint ("127.0.0.1", 4525);
Convert the content you want to send to byte[], and save it to the Usertoken property Socketargs.usertoken = userbytes;
socketargs.completed + = new eventhandler<socketasynceventargs> (socketargs_completed);
Client Step One: initiates a server connection request. Socket.
ConnectAsync (Socketargs); }//each occurrence of a socket operation is said to activate this method, the operation includes (connect/send/receive/none) void socketargs_completed (object sender, SocketAsynceventargs e) {if (e.lastoperation = = Socketasyncoperation.connect) {
Client Step Two: The connection server succeeds, puts the data that needs to be sent into the buffer, and then asynchronously sends a message request to the server byte[] Userbytes = (byte[]) E.usertoken; E.setbuffer (userbytes, 0, Userbytes.
Length); Socket.
SendAsync (e); } else if (e.lastoperation = = socketasyncoperation.send) {//Client step three: Message sent successfully, at this time set a new
instance of the buffer and initiates the message returned by the asynchronous receive server byte[] userbytes = new byte[1024]; E.setbuffer (userbytes, 0, Userbytes.
Length); Socket.
Receiveasync (e); } else if (e.lastoperation = = socketasyncoperation.receive) {//Client step four: Get the message returned to the server , close the socket string receviestr = Encoding.UTF8.GetString (e.buffer, 0, E.buffer.length).
Replace ("n", ""); Because it is an asynchronous socket request, you need to update the Lbshowmessage display with the UI thread This.lbShowMessage.Dispatcher.BegiNinvoke (New Dothingdele (dothing), receviestr); Socket.
Close (); }}//Update UI public void Dothing (string arg) {this.lbShowMessage.Content = this
. lbshowmessage.content + "+" + arg;
}//Declares a dothing method that delegates public delegate void Dothingdele (string arg); }
The client XAML foreground code is as follows:
<grid x:name= "LayoutRoot" background= "white" showgridlines= "True" >
<textbox height= "23" Horizontalalignment= "left" margin= "20,20,0,0"
name= "Tbinput" verticalalignment= "Top" width= "243"/>
<button content= "Send" height= "horizontalalignment=" left "margin=
" 279,20,0,0 "Name=" Button1 " Verticalalignment= "Top"
width= "page" click= "Button1_Click"/>
<sdk:label height= "28" Horizontalalignment= "left" margin= "20,57,0,0"
name= "Lbshowmessage" verticalalignment= "Top" width= "358"/>
</Grid>
The final effect is as follows, if you need source code click Slsocket.zip Download, this article demonstrates the simplest communication effect:
tell me about the socket in Silverlight.
As the "Antique class" category in the. Net framework, the socket class plays an extremely important role in both the 1.0 and the newest 3.5 SP1 network programming. Optimizing the network architecture has always been a problem for developers to pursue. In the 2.0 era, we used asynchronous sockets (Begin, end, and so on) to enhance performance, but such methods tend to initialize a IAsyncResult object, which gives. NET of GC brings additional burdens. Thus, from 2.0 SP1, the. Net Framework Socket class has a new asynchronous approach (async), which, from 2.0, supports communication with the server through an Async socket. Async Socket
Let's start by looking at the difference between using the Async method and the previous method of using Begin and end:
In the case of the Begin and end method, we accept a client using the following method:
Server.beginaccept (New AsyncCallback (Doaccepttcpclientcallback), Server);
And the callback function:
protected void Doaccepttcpclientcallback (IAsyncResult result)
{
//gets current socket
socket listener = result. AsyncState as Socket;
Remote socket Object
Socket client = NULL;
Try
{
//stop synchronizing listening port
client = listener. Endaccept (result);
}
Catch
{
return;
}
if (client = = null)
return;
StateObject state = new StateObject (buffersize);
Begins asynchronously receiving the data client from the remote socket
. BeginReceive (state. Buffer, 0, state. Buffer.length, Socketflags.none,
new AsyncCallback (Dobeginreceivecallback), state);
}
If you use async, it is relatively straightforward to initialize a SocketAsyncEventArgs object:
SocketAsyncEventArgs Accepteventargs = new SocketAsyncEventArgs ();
accepteventargs.completed + = onacceptcompleted;
Server.acceptasync (Accepteventargs);
Then handle the completed event:
protected void onacceptcompleted (object sender, SocketAsyncEventArgs e)
{
if (E.socketerror = = socketerror.success)
{
Socket client = E.acceptsocket;
SocketAsyncEventArgs args = new SocketAsyncEventArgs ();
Args. SetBuffer (new byte[10240], 0, 10240);
args.completed + = onclientreceive;
Client. Receiveasync (args);
Server.acceptasync (Accepteventargs);
}
}
SocketAsyncEventArgs
The core part of the Async socket is the use of the SocketAsyncEventArgs class, which is designed for Web server applications that require high performance. An application can use the enhanced asynchronous pattern entirely, or it can use this mode only in the target hotspot area (for example, when receiving large amounts of data).
The main feature of these enhancements is the ability to avoid duplicate object allocations and synchronizations when the amount of asynchronous socket I/O is very large. The Start/end design pattern currently implemented by the socket class requires that each asynchronous socket operation be assigned a IAsyncResult object.
The SocketAsyncEventArgs class has a completed event that invokes the handler for the event, after all the operations that are related to the async socket. For example, in the example above, we use the Onacceptcompleted method to handle the results after accept. Often we use this class to perform asynchronous socket operations with the following steps: Assigning a new SocketAsyncEventArgs context object, or getting an idle object from the application pool. Set the property of the context object to the action to be performed (for example, the completion callback method, the data buffer, the buffer offset, and the maximum amount of data to be transferred). Call the appropriate socket method (XxxAsync) To initiate an asynchronous operation. If the asynchronous socket method (XxxAsync) Returns True, the context property is queried in the callback to get the completion status. If the asynchronous socket method (XxxAsync) returns false, the operation is completed synchronously. You can query the context property to get the result of the operation. Re-use the context for another operation, put it back into the application pool, or discard it.
You can use the same SocketAsyncEventArgs to handle the results of the Accept (server), Connect (client), Send, receive, SocketAsyncEventArgs has a lastoperation attribute to label the result of this completed operation:
if (e.lastoperation = = Socketasyncoperation.connect)
{
//...
}
else if (e.lastoperation = = socketasyncoperation.receive)
{
//...
}
else if (e.lastoperation = = socketasyncoperation.send)
{
//...
}
Of course, you can also use different SocketAsyncEventArgs objects for different operations.
The result of the call can be judged by observing the SocketError property in the event handler, when
E.socketerror = = Socketerror.success
Indicates that the call was successful.
By calling SocketAsyncEventArgs's SetBuffer method, you set the data that you want to send, or specify the cache array to receive the data. For example, in the example above, we set up a 10240-byte array for args to hold the received data:
Args. SetBuffer (new byte[10240], 0, 10240);
using async sockets in Silverlight
Async sockets are used in Silverlight, except that some methods are not supported, in general and full version. NET is similar. However, there are some small limitations: the range of ports that a network application can connect to must be within the range of 4502-4534. These are the only ports that are allowed to connect using a socket from a Silverlight application. If the destination port of the connection is not within this port range, the attempt to connect will fail. The security policy system in the Silverlight runtime requires that a policy file be downloaded from a network resource before the network connection is allowed to access the resource. Both the source site and cross-domain network access are affected as a result.
For the 2nd above, we use the following form of policy file:
<?xml version= "1.0" encoding = "Utf-8"?>
<access-policy>
<cross-domain-access>
< policy>
<allow-from>
<domain uri= "file:///"/>
</allow-from>
<grant-to >
<socket-resource port= "4502-4506" protocol= "tcp"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
You can set up a server service on your servers and listen to the 943 interface. When Silverlight accesses a server resource through the socket, it first connects to port 943 of the server address and then downloads the policy file. packaged Asyncclient class
Here is an async socket Class I wrote that can be used in Silverlight for socket operations in a virtual lab. Unlike a normal socket, when sending a packet, the class adds 4 bytes to the packet header, which is the length of the packet, and when the packet is received, the first 4 bytes are read as the length of this receive. :
Using System;
Using System.Collections.Generic;
Using System.Linq;
Using System.Text;
Using System.Net.Sockets;
Using System.IO;
Using System.Threading;
Using System.Net;
Using System.ComponentModel;
Namespace Newinfosoft.Net.Sockets {public class Asyncclient:inotifypropertychanged {#region Events <summary>////</summary> public event Asyncconnectioneventhandler when data is received
datarecieved; <summary>////</summary> public event Asyncconnectioneventhandler Dat when data is sent
ASend; <summary>////</summary> public event Asyncconnectioneventhandler Co when the connection server succeeds
nnected; <summary>////When the property is changed (for example, whether the Connection property)///</summary> public event Propertychangedeventhan
Dler propertychanged;
#endregion///<summary>///internal class for storing temporary data at reception///assuming that the data format sent by the server is:| Data length n| data native///4 byte n Bytes//</summary> protected class StateObject {
Public byte[] Buffer;
<summary>///How many bytes of data are not received///</summary> public int remainsize = 0;
public MemoryStream Stream = null;
Public stateobject (int buffersize) {Buffer = new byte[buffersize]; } ~stateobject () {if (Stream! = null) {Stre Am.
Close ();
Stream.dispose (); }}}///<summary> Client socket object////</summary> Public
Socket Client {get; private set;}
#region Async SocketAsyncEventArgs Public SocketAsyncEventArgs Sendeventargs {get; private set;}
Public SocketAsyncEventArgs Receiveeventargs {get; private set;} PublIC SocketAsyncEventArgs Connecteventargs {get; private set;} #endregion///<summary>////StateObject///</summary> protected St for reading or setting reception
Ateobject state {get; set;} <summary>///Send the lock, only the data in the current package is sent all the time, only allow the next package to be sent///</summary> protected Object M_lo
Ckobject = new Object ();
protected ManualResetEvent sendresetevent = new ManualResetEvent (false);
#region isconnecting protected bool m_isconnecting = FALSE;
<summary>////Read or set whether to connect to a remote server for binding operations///</summary> public bool Isconnecting
{get {return m_isconnecting; } set {if (m_isconnecting! = value) {M_iscon
necting = value;
OnPropertyChanged ("isconnecting"); }}} #eNdregion///<summary>/////////IPAddress to create a asyncclient with the specified port, Connect method Connection///</summar y>//<param name= "buffersize" > Receive cache Size </param