在Silverlight中使用Socket进行通信(2)SL与Socket Server进行文本交换

2016-08-20 11:07:37来源:http://wengyuli.blog.51cto.com/44136/587583作者:wengyuli人点击



上一篇博文记录了单纯的socket client和socket server 进行通信的过程, client发送一个数据到服务端,服务端加以处理返回给客户端,基于这种简单demo的方式,这一次我尝试了一下silverlight客户端跟socket服务端之间的通信。


首先我们建立一个监听tcp端口的socket服务,这个服务会一直持续的监听服务并将收到的数据加以包装返回给silverlight客户端,这里需要说明的是由于silverlight客户端最终还是web形式的,如果想与socket进行异步通信,服务端为了安全起见必然要验证一下策略文件并且只提供了4502-4534的端口范围。请求策略时,Silverlight会自己发送一个字符串<policy-file-request/>到服务器的943端口,然后你必须在服务器程序里接收该请求,分析是否是策略请求后,发送一个策略文件的字符串给客户端,客户端接收到策略文件后自己分析完后再发送程序员自己写的数据请求。


Socket Server


首先需要在服务端放一个策略文件,然后建立一个类,这个类是我在网络上找的



代码

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
usingSystem.Net;
usingSystem.Net.Sockets;
usingSystem.IO;
usingSystem.Threading;
usingSystem.Reflection;
usingSystem.Configuration;

namespaceSLSocket
{
publicclassPolicySocketServer
{
TcpListener_Listener=null;
TcpClient_Client=null;
staticManualResetEvent_TcpClientConnected=newManualResetEvent(false);
conststring_PolicyRequestString="<policy-file-request/>";
int_ReceivedLength=0;
byte[]_Policy=null;
byte[]_ReceiveBuffer=null;

privatevoidInitializeData()
{
stringpolicyFile="SocketClientAccessPolicy.xml";
using(FileStreamfs=newFileStream(policyFile,FileMode.Open))
{
_Policy=newbyte[fs.Length];
fs.Read(_Policy,0,_Policy.Length);
}
_ReceiveBuffer=newbyte[_PolicyRequestString.Length];
}
publicvoidStartSocketServer()
{
InitializeData();

try
{
_Listener=newTcpListener(IPAddress.Any,943);
_Listener.Start();
while(true)
{
_TcpClientConnected.Reset();
_Listener.BeginAcceptTcpClient(newAsyncCallback(OnBeginAccept),null);
_TcpClientConnected.WaitOne();
}
}
catch(Exception)
{
}
}

privatevoidOnBeginAccept(IAsyncResultar)
{
_Client=_Listener.EndAcceptTcpClient(ar);
_Client.Client.BeginReceive(_ReceiveBuffer,0,_PolicyRequestString.Length,SocketFlags.None,
newAsyncCallback(OnReceiveComplete),null);
}

privatevoidOnReceiveComplete(IAsyncResultar)
{
try
{
_ReceivedLength+=_Client.Client.EndReceive(ar);
if(_ReceivedLength<_PolicyRequestString.Length)
{
_Client.Client.BeginReceive(_ReceiveBuffer,_ReceivedLength,
_PolicyRequestString.Length-_ReceivedLength,
SocketFlags.None,newAsyncCallback(OnReceiveComplete),null);
return;
}
stringrequest=System.Text.Encoding.UTF8.GetString(_ReceiveBuffer,0,_ReceivedLength);
if(StringComparer.InvariantCultureIgnoreCase.Compare(request,_PolicyRequestString)!=0)
{
_Client.Client.Close();
return;
}
_Client.Client.BeginSend(_Policy,0,_Policy.Length,SocketFlags.None,
newAsyncCallback(OnSendComplete),null);
}
catch(Exception)
{
_Client.Client.Close();
}
_ReceivedLength=0;
_TcpClientConnected.Set();//Allowwaitingthreadtoproceed
}

privatevoidOnSendComplete(IAsyncResultar)
{
try
{
_Client.Client.EndSendFile(ar);
}
catch(Exception)
{
}
finally
{
_Client.Client.Close();
}
}
}
}





socket 服务的形式是控制台程序,由于正在做一个聊天的工具,所以原理是这样的,AB都会向服务器发出请求,后发请求的那个会接收到先发请求人的IP和端口,以方便进行后续通信的建立。其中代码如下:



代码

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Net.Sockets;
usingSystem.Threading;
usingSystem.Collections;
usingSystem.IO;
usingSystem.Net;
usingSystem.Data;
usingSystem.ComponentModel;
namespaceSLSocket
{
publicclassUserSocket
{
publicstringAddress{set;get;}
publicintPort{set;get;}
publicstringUserName{set;get;}
publicDateTimeStoreTime{set;get;}
}
classProgram
{
staticList<UserSocket>listUserSocket=newList<UserSocket>();
privateconststringSERVER_IP="127.0.0.1";
privateconstintSERVER_PORT=4530;//注意监听端口在4502-4534之间
staticvoidMain(string[]args)
{
try
{
#regionStartThePolicyServer验证策略文件
PolicySocketServerStartPolicyServer=newPolicySocketServer();
Threadth=newThread(newThreadStart(StartPolicyServer.StartSocketServer));
th.IsBackground=true;
th.Start();
#endregion

IPEndPointlocalEndPoint=newIPEndPoint(IPAddress.Parse(SERVER_IP),SERVER_PORT);
Socketlistener=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
listener.Bind(localEndPoint);
listener.Listen(-1);
Console.WriteLine("等待客户端连接...");
while(true)
{
SocketclientSocket=listener.Accept();
if(clientSocket.Connected)
{
EndPointremoteEp=clientSocket.RemoteEndPoint;
IPEndPointip=(IPEndPoint)remoteEp;
Console.WriteLine(ip.Address+":"+ip.Port.ToString()+"已经连接到服务器");

ThreadmyThread=newThread(newParameterizedThreadStart(SocketThread));
myThread.Start(clientSocket);
}
}
}
catch
{}
}

staticvoidSocketThread(objectclientSocket)//处理接收到的socket请求
{
try
{
Socketclient=(Socket)clientSocket;
IPEndPointaddress=(IPEndPoint)client.RemoteEndPoint;
byte[]bytData=newbyte[1024];
intreceivedLength=client.Receive(bytData);
stringstrUserAndPartner=System.Text.Encoding.UTF8.GetString(bytData,0,receivedLength);
stringstrUserName=strUserAndPartner.Split('-')[0];
stringstrPartnerName=strUserAndPartner.Split('-')[1];

listUserSocket.Add(newUserSocket(){Address=address.Address.ToString(),Port=address.Port,UserName=strUserName});
Console.WriteLine("存储了【"+strUserName+"】的地址【"+address.Address.ToString()+":"+address.Port.ToString()+"】");
Console.WriteLine("当前的存储的客户端标识数量"+listUserSocket.Count.ToString());
UserSocketuserSocket=listUserSocket.Where(m=>m.UserName==strPartnerName).FirstOrDefault();
if(userSocket!=null)
{
Socketrev=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
rev.Connect(newIPEndPoint(IPAddress.Parse(address.Address.ToString()),4530));
rev.Send(System.Text.Encoding.UTF8.GetBytes(userSocket.Address+"-"+userSocket.Port.ToString()));
rev.Close();
Console.WriteLine("向客户端发送了聊天对象【"+userSocket.UserName+"】的地址:【"+userSocket.Address+":"+userSocket.Port.ToString()+"】");
}
}
catch
{}
}
}
}





这样一个服务端就建立完成了,作用是接收请求并返回聊天对象的IP和端口。




Silverlight客户端

客户端的功能就是利用silverlight中提供的socket类来请求服务器,并接收到服务器返回的数据,







代码

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Net;
usingSystem.Windows;
usingSystem.Windows.Controls;
usingSystem.Windows.Documents;
usingSystem.Windows.Input;
usingSystem.Windows.Media;
usingSystem.Windows.Media.Animation;
usingSystem.Windows.Shapes;
usingSystem.IO.IsolatedStorage;
usingSystem.Net.Sockets;
usingSystem.Text;
usingSystem.Threading;

namespacesilverlight
{
publicpartialclassMainPage:UserControl
{
privatestaticstringUSERNAME="";
privatestaticstringPARTNERNAME="";

privateSocketclientSocket=null;
privateSocketlistener=null;

privateconststringSERVER_IP="127.0.0.1";
privateconstintSERVER_PORT=4530;

publicMainPage()
{
InitializeComponent();

this.button1.Click+=newRoutedEventHandler(button1_Click);
}

voidbutton1_Click(objectsender,RoutedEventArgse)
{
USERNAME=this.txtUser.Text;
PARTNERNAME=this.txtPartner.Text;
//初始化
clientSocket=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
SocketAsyncEventArgssocketEventArg=newSocketAsyncEventArgs()
{
RemoteEndPoint=newIPEndPoint(IPAddress.Parse(SERVER_IP),SERVER_PORT)
};
socketEventArg.Completed+=newEventHandler<SocketAsyncEventArgs>(socketEventArg_Completed);
clientSocket.ConnectAsync(socketEventArg);
AddText("连接服务器...");
}
//连接成功后开始发送
voidsocketEventArg_Completed(objectsender,SocketAsyncEventArgse)
{
if(e.SocketError==SocketError.Success)
{
AddText("已连接服务器!");
stringstrSend=USERNAME+"-"+PARTNERNAME;
byte[]bytSend=Encoding.UTF8.GetBytes(strSend);
SocketAsyncEventArgssocketArg=newSocketAsyncEventArgs();
socketArg.Completed+=newEventHandler<SocketAsyncEventArgs>(socketArg_Completed);
socketArg.SetBuffer(bytSend,0,bytSend.Length);
clientSocket.SendAsync(socketArg);
AddText("向服务器发送信息...");
}
}

voidsocketArg_Completed(objectsender,SocketAsyncEventArgse)
{
//发送成功
if(e.SocketError==SocketError.Success)
{
AddText("已经将自己的IP和聊天对象发送到服务器");
}
//监听服务器回传的信息
Threadthread=newSystem.Threading.Thread(newSystem.Threading.ThreadStart(listenSocket));
thread.Start();
}
//监听服务端发来的消息
voidlistenSocket()
{
AddText("开始监听服务器回传消息...");
listener=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
SocketAsyncEventArgssocketEventArg=newSocketAsyncEventArgs();
socketEventArg.Completed+=newEventHandler<SocketAsyncEventArgs>(socketConnectEventArg_Completed);
clientSocket.ConnectAsync(socketEventArg);
}

voidsocketConnectEventArg_Completed(objectsender,SocketAsyncEventArgse)
{
SocketAsyncEventArgslistenerSocketAsyncEventArgs=newSocketAsyncEventArgs();
listenerSocketAsyncEventArgs.RemoteEndPoint=newIPEndPoint(IPAddress.Parse(SERVER_IP),SERVER_PORT);
byte[]byteReceive=newbyte[12000];
listenerSocketAsyncEventArgs.Completed+=newEventHandler<SocketAsyncEventArgs>(listenerSocketAsyncEventArgs_Completed);
listenerSocketAsyncEventArgs.SetBuffer(byteReceive,0,byteReceive.Length);
listener.ReceiveAsync(listenerSocketAsyncEventArgs);
}

voidlistenerSocketAsyncEventArgs_Completed(objectsender,SocketAsyncEventArgse)
{
if(e.SocketError==SocketError.Success)
{
byte[]byteReceive=e.Buffer;
stringstrText=System.Text.Encoding.UTF8.GetString(byteReceive,0,byteReceive.Length);
AddText("成功接收到服务器回传的消息"+strText);
}
}

voidAddText(stringstrText)
{
if(this.textBox1.Dispatcher.CheckAccess())
{
this.textBox1.Text+=strText+Environment.NewLine;
}
else
{
this.textBox1.Dispatcher.BeginInvoke(()=>{this.textBox1.Text+=strText+Environment.NewLine;});
}
}
}
}









最近在做 Silverlight p2p方面的开发,正在研究能不能这么做,因为网上搜到的silverlight做P2P唯一的一个例子是借助于windows Live Message 做的,而这个不太现实呵呵,但是目前看silverlight中提供的socket类,仅仅只是接收和发送的类,并没有socket服务端的方法,所以也许短期内 在silverlight上做端到端的视频对话,是不可能了,下一步将会把之前利用服务端进行视频聊天的一个demo做完善,希望在这方面有研究的朋友共同交流。




最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台