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

简介:

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

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

Socket Server

 

  

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

 

代码
using  System; 
using  System.Collections.Generic; 
using  System.Text; 
using  System.Net; 
using  System.Net.Sockets; 
using  System.IO; 
using  System.Threading; 
using  System.Reflection; 
using  System.Configuration; 

namespace  SLSocket 

    
public   class  PolicySocketServer 
    { 
        TcpListener _Listener 
=   null
        TcpClient _Client 
=   null
        
static  ManualResetEvent _TcpClientConnected  =   new  ManualResetEvent( false ); 
        
const   string  _PolicyRequestString  =   " <policy-file-request/> "
        
int  _ReceivedLength  =   0
        
byte [] _Policy  =   null
        
byte [] _ReceiveBuffer  =   null

        
private   void  InitializeData() 
        { 
            
string  policyFile  =   " SocketClientAccessPolicy.xml "
            
using  (FileStream fs  =   new  FileStream(policyFile, FileMode.Open)) 
            { 
                _Policy 
=   new   byte [fs.Length]; 
                fs.Read(_Policy, 
0 , _Policy.Length); 
            } 
            _ReceiveBuffer 
=   new   byte [_PolicyRequestString.Length]; 
        } 
        
public   void  StartSocketServer() 
        { 
            InitializeData(); 

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

        
private   void  OnBeginAccept(IAsyncResult ar) 
        { 
            _Client 
=  _Listener.EndAcceptTcpClient(ar); 
            _Client.Client.BeginReceive(_ReceiveBuffer, 
0 , _PolicyRequestString.Length, SocketFlags.None, 
                
new  AsyncCallback(OnReceiveComplete),  null ); 
        } 

        
private   void  OnReceiveComplete(IAsyncResult ar) 
        { 
            
try  
            { 
                _ReceivedLength 
+=  _Client.Client.EndReceive(ar); 
                
if  (_ReceivedLength  <  _PolicyRequestString.Length) 
                { 
                    _Client.Client.BeginReceive(_ReceiveBuffer, _ReceivedLength, 
                        _PolicyRequestString.Length 
-  _ReceivedLength, 
                        SocketFlags.None, 
new  AsyncCallback(OnReceiveComplete),  null ); 
                    
return
                } 
                
string  request  =  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, 
                    
new  AsyncCallback(OnSendComplete),  null ); 
            } 
            
catch  (Exception) 
            { 
                _Client.Client.Close(); 
            } 
            _ReceivedLength 
=   0
            _TcpClientConnected.Set(); 
// Allow waiting thread to proceed 
        } 

        
private   void  OnSendComplete(IAsyncResult ar) 
        { 
            
try  
            { 
                _Client.Client.EndSendFile(ar); 
            } 
            
catch  (Exception) 
            { 
            } 
            
finally  
            { 
                _Client.Client.Close(); 
            } 
        } 
    } 
}

 

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

 

代码
using  System;   
using  System.Collections.Generic;   
using  System.Linq;   
using  System.Text;   
using  System.Net.Sockets;   
using  System.Threading;   
using  System.Collections;   
using  System.IO;   
using  System.Net;   
using  System.Data;   
using  System.ComponentModel;   
namespace  SLSocket 

    
public   class  UserSocket 
    { 
        
public   string  Address {  set get ; } 
        
public   int  Port {  set get ; } 
        
public   string  UserName {  set get ; } 
        
public  DateTime StoreTime {  set get ; } 
    } 
    
class  Program   
    { 
        
static  List < UserSocket >  listUserSocket  =   new  List < UserSocket > (); 
        
private   const   string  SERVER_IP  =   " 127.0.0.1 "
        
private   const   int  SERVER_PORT  =   4530 ; // 注意监听端口在4502-4534之间 
         static   void  Main( string [] args)   
        { 
            
try  
            { 
                
#region  Start The Policy Server 验证策略文件 
                PolicySocketServer StartPolicyServer 
=   new  PolicySocketServer(); 
                Thread th 
=   new  Thread( new  ThreadStart(StartPolicyServer.StartSocketServer)); 
                th.IsBackground 
=   true
                th.Start(); 
                
#endregion  

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

                        Thread myThread 
=   new  Thread( new  ParameterizedThreadStart(SocketThread)); 
                        myThread.Start(clientSocket); 
                    } 
                } 
            } 
            
catch  
            { } 
        } 

        
static   void  SocketThread( object  clientSocket) // 处理接收到的socket请求    
        { 
            
try  
            { 
               Socket client 
=  (Socket)clientSocket; 
               IPEndPoint address 
=  (IPEndPoint)client.RemoteEndPoint; 
               
byte [] bytData  =   new   byte [ 1024 ]; 
               
int  receivedLength  =  client.Receive(bytData); 
               
string  strUserAndPartner  =  System.Text.Encoding.UTF8.GetString(bytData,  0 , receivedLength); 
               
string  strUserName  =  strUserAndPartner.Split( ' - ' )[ 0 ]; 
               
string  strPartnerName  =  strUserAndPartner.Split( ' - ' )[ 1 ]; 

               listUserSocket.Add(
new  UserSocket() { Address  =  address.Address.ToString(), Port  =  address.Port, UserName  =  strUserName }); 
               Console.WriteLine(
" 存储了【 " + strUserName + " 】的地址【 " + address.Address.ToString() + " : " + address.Port.ToString() + " " ); 
               Console.WriteLine(
" 当前的存储的客户端标识数量 " + listUserSocket.Count.ToString()); 
               UserSocket userSocket 
=  listUserSocket.Where(m => m.UserName == strPartnerName).FirstOrDefault(); 
               
if  (userSocket  !=   null
               { 
                   Socket rev 
=   new  Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
                   rev.Connect(
new  IPEndPoint(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类来请求服务器,并接收到服务器返回的数据,


 

代码
using  System; 
using  System.Collections.Generic; 
using  System.Linq; 
using  System.Net; 
using  System.Windows; 
using  System.Windows.Controls; 
using  System.Windows.Documents; 
using  System.Windows.Input; 
using  System.Windows.Media; 
using  System.Windows.Media.Animation; 
using  System.Windows.Shapes; 
using  System.IO.IsolatedStorage; 
using  System.Net.Sockets; 
using  System.Text; 
using  System.Threading; 

namespace  silverlight 

    
public   partial   class  MainPage : UserControl 
    { 
        
private   static   string  USERNAME = ""
        
private   static   string  PARTNERNAME  =   ""

        
private   Socket clientSocket  =   null
        
private   Socket listener  =   null

        
private   const   string  SERVER_IP  =   " 127.0.0.1 "
        
private   const   int  SERVER_PORT  =   4530

        
public  MainPage() 
        { 
            InitializeComponent(); 

            
this .button1.Click += new  RoutedEventHandler(button1_Click); 
        } 

        
void  button1_Click( object  sender, RoutedEventArgs e) 
        { 
            USERNAME 
=   this .txtUser.Text; 
            PARTNERNAME 
=   this .txtPartner.Text; 
            
// 初始化        
            clientSocket  =   new  Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
            SocketAsyncEventArgs socketEventArg 
=   new  SocketAsyncEventArgs() 
            { 
                RemoteEndPoint 
=   new  IPEndPoint(IPAddress.Parse(SERVER_IP), SERVER_PORT) 
            }; 
            socketEventArg.Completed 
+= new  EventHandler < SocketAsyncEventArgs > (socketEventArg_Completed); 
            clientSocket.ConnectAsync(socketEventArg); 
            AddText(
" 连接服务器... " ); 
        }          
        
//  连接成功后 开始发送 
         void  socketEventArg_Completed( object  sender, SocketAsyncEventArgs e) 
        { 
            
if  (e.SocketError  ==  SocketError.Success) 
            { 
                AddText(
" 已连接服务器! " ); 
                
string  strSend  =  USERNAME + " - " + PARTNERNAME; 
                
byte [] bytSend  =  Encoding.UTF8.GetBytes(strSend); 
                SocketAsyncEventArgs socketArg 
=   new  SocketAsyncEventArgs(); 
                socketArg.Completed 
+=   new  EventHandler < SocketAsyncEventArgs > (socketArg_Completed); 
                socketArg.SetBuffer(bytSend, 
0 , bytSend.Length); 
                clientSocket.SendAsync(socketArg); 
                AddText(
" 向服务器发送信息... " );                
            }            
        } 

        
void  socketArg_Completed( object  sender, SocketAsyncEventArgs e) 
        { 
             
// 发送成功 
             if  (e.SocketError  ==  SocketError.Success) 
            { 
                AddText(
" 已经将自己的IP和聊天对象发送到服务器 " ); 
            } 
            
// 监听服务器回传的信息 
            Thread thread  =   new  System.Threading.Thread( new  System.Threading.ThreadStart(listenSocket)); 
            thread.Start(); 
        } 
        
// 监听服务端发来的消息 
         void  listenSocket() 
        { 
            AddText(
" 开始监听服务器回传消息... " ); 
            listener 
=   new  Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
            SocketAsyncEventArgs socketEventArg 
=   new  SocketAsyncEventArgs(); 
            socketEventArg.Completed 
+=   new  EventHandler < SocketAsyncEventArgs > (socketConnectEventArg_Completed); 
            clientSocket.ConnectAsync(socketEventArg);    
        } 

        
void  socketConnectEventArg_Completed( object  sender, SocketAsyncEventArgs e) 
        { 
            SocketAsyncEventArgs listenerSocketAsyncEventArgs 
=   new  SocketAsyncEventArgs(); 
            listenerSocketAsyncEventArgs.RemoteEndPoint 
=   new  IPEndPoint(IPAddress.Parse(SERVER_IP), SERVER_PORT); 
            
byte [] byteReceive  =   new   byte [ 12000 ]; 
            listenerSocketAsyncEventArgs.Completed 
+=   new  EventHandler < SocketAsyncEventArgs > (listenerSocketAsyncEventArgs_Completed); 
            listenerSocketAsyncEventArgs.SetBuffer(byteReceive, 
0 , byteReceive.Length); 
            listener.ReceiveAsync(listenerSocketAsyncEventArgs); 
        } 

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

        
void  AddText( string  strText) 
        { 
            
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做完善,希望在这方面有研究的朋友共同交流。

 





     本文转自wengyuli 51CTO博客,原文链接:http://blog.51cto.com/wengyuli/587583,如需转载请自行联系原作者





相关文章
|
29天前
|
数据处理 C# C++
如何使用C#和C++结构体实现Socket通信
如何使用C#和C++结构体实现Socket通信
|
3月前
|
网络协议 程序员 Python
揭秘Python网络编程:深入理解Socket通信
在当今信息时代,网络通信已经成为人们生活中不可或缺的一部分。而Python作为一种高效、易用的编程语言,自然也能够很好地支持网络编程和Socket通信。本文将介绍Python网络编程与Socket通信的相关知识,包括Socket通信模型、Socket编程接口、网络套接字等内容。
|
3月前
|
网络协议 开发者 Python
Python网络编程与Socket通信:连接世界的无限可能
在当今数字化时代,Python作为一种强大的编程语言,通过网络编程与Socket通信为我们打开了连接世界的无限可能。本文将深入探讨Python网络编程的基础知识、Socket通信的原理以及实际应用,帮助读者更好地理解并运用这一技术。
|
3月前
|
网络协议
【Netty 网络通信】Socket 通信原理
【1月更文挑战第9天】【Netty 网络通信】Socket 通信原理
|
5月前
|
存储 Cloud Native Linux
C++封装了socket通信类
C++封装了socket通信类
|
6月前
|
存储
14.10 Socket 套接字选择通信
对于网络通信中的服务端来说,显然不可能是一对一的,我们所希望的是服务端启用一份则可以选择性的与特定一个客户端通信,而当不需要与客户端通信时,则只需要将该套接字挂到链表中存储并等待后续操作,套接字服务端通过多线程实现存储套接字和选择通信,可以提高服务端的并发性能,使其能够同时处理多个客户端的请求。在实际应用场景中,这种技术被广泛应用于网络编程、互联网应用等领域。在服务端启动时,创建套接字并进行绑定,然后开启一个线程(称为主线程)用于监听客户端的连接请求。主线程在接收到新的连接请求后,会将对应的套接字加入一个数据结构(例如链表、队列、哈希表等)中进行存储。同时,主线程会将存储套接字的数据结构传递给
25 1
14.10 Socket 套接字选择通信
|
6月前
14.5 Socket 应用组播通信
组播通信是一种基于UDP协议的网络通信方式,它允许发送方将消息同时传递给多个接收方。在组播通信中,发送方和接收方都会加入一个共同的组播组,这个组播组对应一个特定的IP地址,所有加入该组播组的主机都能够接收到发送方发送的消息。组播通信可以有效地减少网络流量和网络负载,因为在传统的点对点通信方式下,每个消息都需要单独传输到每个接收方,而在组播通信中,每个消息只需要传输一次,就可以同时传递给多个接收方。在使用组播模式时,需要在套接字上使用`setsockopt()`函数来设置套接字的`IP_MULTICAST_IF`选项,指定本地主机的出站接口地址,用于发送组播数据包。此外,还可以设置`IP_ADD
58 0
14.5 Socket 应用组播通信
|
14天前
|
网络协议 Unix Linux
Socket通信详细介绍1
Socket通信详细介绍
24 0
|
2月前
|
C++
C++实现Socket连接通信
C++实现Socket连接通信
13 1