深入探索Silverlight网络通信:从策略服务器到本地连接
立即解锁
发布时间: 2025-08-13 03:16:13 阅读量: 12 订阅数: 36 

### 深入探索Silverlight网络通信:从策略服务器到本地连接
#### 1. 策略服务器相关
策略服务器在Silverlight网络通信中扮演着重要角色。当策略服务器停止时,会执行如下代码:
```vb
policyServer.Stop()
Console.WriteLine("Policy server shut down.")
End Sub
```
策略连接类(PolicyConnection)的任务相对简单。创建时,它会存储对策略文件数据的引用。当调用`HandleRequest()`方法时,代码会访问新连接的网络流并尝试从中读取数据。如果一切正常,客户端会发送包含“<policy-file-request/>”文本的字符串。读取该字符串后,客户端会将策略数据写入该流并关闭连接。以下是完整代码:
```vb
Public Class PolicyConnection
Private client As TcpClient
Private policy As Byte()
Public Sub New(ByVal client As TcpClient, ByVal policy As Byte())
Me.client = client
Me.policy = policy
End Sub
' The request that the client sends.
Private Shared policyRequestString As String = "<policy-file-request/>"
Public Sub HandleRequest()
Dim s As Stream = client.GetStream()
' Read the policy request string.
' This code doesn't actually check the content of the request string.
' Instead, it returns the policy for every request.
Dim buffer As Byte() = New Byte(policyRequestString.Length - 1){}
' Only wait 5 seconds. That way, if you attempt to read the request string
' and it isn't there or it's incomplete, the client only waits for 5
' seconds before timing out.
client.ReceiveTimeout = 5000
s.Read(buffer, 0, buffer.Length)
' Send the policy.
s.Write(policy, 0, policy.Length)
' Close the connection.
client.Close()
Console.WriteLine("Served policy file.")
End Sub
End Class
```
不过,目前还无法测试策略服务器,因为Silverlight不允许显式请求策略文件,而是在尝试使用基于套接字的应用程序时自动请求。在构建基于套接字应用程序的客户端之前,需要先构建服务器。
#### 2. 消息服务器
消息服务器可以作为单独的应用程序创建,但将其与策略服务器放在同一个应用程序中会更整洁。因为策略服务器在单独的线程上进行监听和请求处理工作,所以消息服务器可以同时工作。
消息服务器和策略服务器类似,也分为两个类:`MessengerServer`用于监听请求并跟踪客户端,`MessengerConnection`用于处理单个客户端的交互。
消息服务器与策略服务器有以下不同点:
- **监听端口**:Silverlight允许基于套接字的应用程序使用4502到4534之间的有限端口范围,消息服务器使用端口4530,代码如下:
```vb
listener = New TcpListener(IPAddress.Any, 4530)
```
- **处理连接请求**:当消息服务器收到连接请求时,除了创建一个新类的实例(`MessengerConnection`)来处理通信外,还会将客户端添加到一个集合中,以便跟踪所有当前连接的用户。相关代码如下:
```vb
Private clientNum As Integer
Private clients As New List(Of MessengerConnection)
clientNum += 1
Console.WriteLine("Messenger client #" & clientNum.ToString() & " connected.")
' Create a new object to handle this connection.
Dim clientHandler As New MessengerConnection(client, "Client " & _
clientNum.ToString(), Me)
clientHandler.Start()
SyncLock clients
clients.Add(clientHandler)
End SyncLock
```
由于可能有多个客户端同时连接,在添加客户端之前需要锁定`clients`集合,以避免线程错误。当消息服务器停止时,会遍历整个集合并确保每个客户端都断开连接:
```vb
For Each client As MessengerConnection In clients
client.Close()
Next
```
消息服务器目前还缺少消息传递功能,即一个客户端提交消息并将其传递给所有客户端的能力。要实现此功能,需要在`MessengerConnection`类中处理消息提交,在`MessengerServer`类中处理消息传递。
当`MessengerConnection`对象创建并调用其`Start()`方法时,它会开始监听任何数据:
```vb
Public Sub Start()
Try
' Listen for messages.
client.Client.BeginReceive(message, 0, message.Length, SocketFlags.None, _
New AsyncCallback(AddressOf OnDataReceived), Nothing)
Catch se As SocketException
Console.WriteLine(se.Message)
End Try
End Sub
```
当客户端发送数据时,`OnDataReceived()`回调会被触发。它会逐字节读取数据,直到获取客户端发送的所有信息,然后将数据传递给`MessengerServer.Deliver()`方法,并开始监听下一条消息:
```vb
Public Sub OnDataReceived(ByVal asyn As IAsyncResult)
Try
Dim bytesRead As Integer = client.Client.EndReceive(asyn)
If bytesRead > 0 Then
' Ask the server to send the message to all the clients.
server.DeliverMessage(message, bytesRead)
' Listen for more messages.
client.Client.BeginReceive(message, 0, message.Length, _
SocketFlags.None, New AsyncCallback(AddressOf OnDataReceived), _
Nothing)
End If
Catch err As Exception
Console.WriteLine(err.Message)
End Try
End Sub
```
`MessengerServer.DeliverMessage()`方法会遍历客户端集合,并调用每个客户端的`ReceiveMessage()`方法来传递通信内容。为避免线程问题,该方法会先创建集合的快照副本,然后使用该副本传递消息:
```vb
Public Sub DeliverMessage(ByVal message As Byte(), ByVal bytesRead As Integer)
Console.WriteLine("Delivering message.")
' Duplicate the collection to prevent threading issues.
Dim connectedClients As MessengerConnection()
SyncLock clients
connectedClients = clients.ToArray()
End SyncLock
For Each client As MessengerConnection In connectedClients
Try
client.ReceiveMessage(message, bytesRead)
Catch
' Client is disconnected.
' Remove the client to avoid future attempts.
SyncLock clients
clients.Remove(client)
End SyncLock
client.Close()
End Try
Next
End Sub
```
`MessengerConnection.ReceiveMessage()`方法会将消息数据写回网络流,以便客户端可以接收:
```vb
Public Sub ReceiveMessage(ByVal data As Byte(), ByVal bytesRead As Integer)
client.GetStream().Write(data, 0, bytesRead)
End Sub
```
最后,需要修改启动代码,使应用程序同时创建并启动策略服务器和消息服务器:
```vb
Shared Sub Main(ByVal args As String())
```
0
0
复制全文
相关推荐










