深入探索Silverlight网络通信:从策略服务器到本地连接
立即解锁
发布时间: 2025-08-26 01:42:34 阅读量: 14 订阅数: 47 AIGC 

### 深入探索Silverlight网络通信:从策略服务器到本地连接
#### 1. 策略服务器与策略连接类
策略服务器是网络通信中的重要组成部分。策略连接类 `PolicyConnection` 的任务相对简单。创建该类实例时,它会存储对策略文件数据的引用。当调用 `HandleRequest()` 方法时,代码会访问新连接的网络流并尝试从中读取数据。若一切正常,客户端会发送包含文本 “<policy-file-request/>” 的字符串。读取该字符串后,客户端会将策略数据写入该流并关闭连接。以下是完整代码:
```csharp
public class PolicyConnection
{
private TcpClient client;
private byte[] policy;
public PolicyConnection(TcpClient client, byte[] policy)
{
this.client = client;
this.policy = policy;
}
// The request that the client sends.
private static string policyRequestString = "<policy-file-request/>";
public void HandleRequest()
{
Stream s = 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.
byte[] buffer = new byte[policyRequestString.Length];
// 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.");
}
}
```
目前,我们已经有了一个完整且功能齐全的策略服务器。但遗憾的是,暂时无法对其进行测试,因为Silverlight不允许显式请求策略文件,而是在尝试使用基于套接字的应用程序时自动请求。在为该基于套接字的应用程序构建客户端之前,需要先构建服务器。
#### 2. 消息服务器
消息服务器可以作为一个单独的应用程序创建,但将其与策略服务器放在同一个应用程序中会更整洁。由于策略服务器在单独的线程上进行监听和请求处理工作,消息服务器可以同时开展工作。
消息服务器和策略服务器类似,也分为两个类:`MessengerServer` 用于监听请求并跟踪客户端,`MessengerConnection` 用于处理单个客户端的交互。
消息服务器与策略服务器有以下不同点:
- **监听端口**:Silverlight允许基于套接字的应用程序使用4502到4534范围内的任何端口,消息服务器使用端口4530,代码如下:
```csharp
listener = new TcpListener(IPAddress.Any, 4530);
```
- **处理连接请求**:当消息服务器收到连接请求时,除了创建一个新类(`MessengerConnection`)的实例来处理通信外,还会将客户端添加到一个集合中,以便跟踪所有当前连接的用户。以下是相关代码:
```csharp
private int clientNum;
private List<MessengerConnection> clients = new List<MessengerConnection>();
// 当客户端连接时
clientNum++;
Console.WriteLine("Messenger client #" + clientNum.ToString() + " connected.");
// Create a new object to handle this connection.
MessengerConnection clientHandler = new MessengerConnection(client,
"Client " + clientNum.ToString(), this);
clientHandler.Start();
lock (clients)
{
clients.Add(clientHandler);
}
```
当消息服务器停止时,会遍历整个集合,确保每个客户端都断开连接:
```csharp
foreach (MessengerConnection client in clients)
{
client.Close();
}
```
目前,消息服务器的基本框架已设计完成,但还缺少消息传递功能,即一个客户端提交的消息能传递给所有客户端。要实现此功能,需要在 `MessengerConnection` 类中处理消息提交,在 `MessengerServer` 类中处理消息传递。
以下是 `MessengerConnection` 类中开始监听数据的代码:
```csharp
public void Start()
{
try
{
// Listen for messages.
client.Client.BeginReceive(message, 0, message.Length,
SocketFlags.None, new AsyncCallback(OnDataReceived), null);
}
catch (SocketException se)
{
Console.WriteLine(se.Message);
}
}
```
当客户端发送数据时,`OnDataReceived()` 回调会被触发,它会逐字节读取客户端发送的所有信息,然后将数据传递给 `MessengerServer.Deliver()` 方法,并开始监听下一条消息:
```csharp
public void OnDataReceived(IAsyncResult asyn)
{
try
{
int bytesRead = client.Client.EndReceive(asyn);
if (bytesRead > 0)
{
// 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(OnDataReceived), null);
}
}
catch (Exception err)
{
Console.WriteLine(err.Message);
}
}
```
`MessengerServer.DeliverMessage()` 方法会遍历客户端集合,并调用每个客户端的 `ReceiveMessage()` 方法来传递通信内容。为避免线程问题,该方法会先创建集合的快照副本,然后使用该副本传递消息:
```csharp
public void DeliverMessage(byte[] message, int bytesRead)
{
Console.WriteLine("Delivering message.");
// Duplicate the collection to prevent threading issues.
MessengerConnection[] connectedClients;
lock (clients)
{
connectedClients = clients.ToArray();
}
foreach (MessengerConnection client in connectedClients)
{
try
{
client.ReceiveMessage(message, bytesRead);
}
catch
{
// Client is disconnected.
// Remove the client to avoid future attempts.
lock (clients)
{
clients.Remove(client);
}
client.Close();
}
}
}
```
`MessengerConnection.ReceiveMessage()` 方法会将消息数据写回网络流,以便客户端接收:
```csharp
public void ReceiveMessage(byte[]
```
0
0
复制全文
相关推荐









