带 Windows 服务、C# .NET Remoting 的聊天应用程序






4.71/5 (5投票s)
一个带 Windows 服务、C# .NET Remoting 的聊天应用程序。
引言
这是一个使用 Windows 服务和 .NET Remoting 的示例聊天应用程序。它不是像你在现实世界中看到的那么完整的聊天应用程序,但它能让你熟悉 Windows 服务和 .NET Remoting。
背景
.NET Remoting 广泛用于实现进程间通信。你可以使用一个客户端应用程序,该应用程序在同一台计算机或其他任何计算机上的另一个进程中使用对象。
要使用 .NET Remoting 构建一个应用程序,其中两个组件直接跨应用程序域边界进行通信,你只需要构建以下内容:
- 一个可远程对象。
- 一个主机应用程序域,用于监听对该对象的请求。
- 一个客户端应用程序域,用于对该对象发出请求。
使用代码
此示例向你展示了如何拥有一个带有托管的可远程对象的聊天服务器,并让多个客户端应用程序共享该对象。此示例包含三个不同的解决方案:
- RemoteHello:这是一个可远程对象,将由聊天服务器托管。
- ChatServer:这是将作为聊天服务器的 Windows 服务。它还将托管多个客户端将使用的可远程对象。
- ChatClient1:这是将连接到聊天服务器的客户端应用程序。
创建此应用程序的步骤
- 创建一个可远程对象:RemoteHello 是一个控制台应用程序,其中包含一个 ChatServerObject.cs 类文件。此类继承自
System.MarshaByRefObject
。MarshalByRefObject
是通过代理交换消息而在应用程序域边界之间通信的对象的基类。不继承自MarshalByRefObject
的对象默认为值传递。当远程应用程序引用值传递对象时,对象的副本将跨应用程序域边界传递。 - 创建一个将作为聊天服务器的 Windows 服务:当你创建一个新的 Windows 服务时,你会看到已经添加了两个重写方法:
OnStart
和OnStop
。在OnStart
方法中,我们将选择将用于与客户端通信的通道。我将使用HttpChannel
,它将使用 HTTP 协议传输消息。选择并注册通道后,将可远程对象注册到此服务。 ServiceInstaller1
serviceProcessInstaller1
- 创建客户端应用程序.
- 创建一个
HTTPChannel
并注册它。 - 注册
wellKnownClientType
。 - 创建托管在服务器上的远程对象的代理。
- 创建一个新线程,该线程运行一个无限
for
循环,该循环执行两项操作: - 从服务器获取总客户端数。
- 从服务器获取聊天文本。
构建此应用程序,你将看到创建了 RemoteHello.dll。现在,你需要将此 RemoteHello.dll 的引用添加到 ChatServer 和 ChatClient1。之所以需要将其添加到 ChatClient,是为了在客户端创建可远程对象的代理。
namespace RemoteHello
{
public class ChatServerObject : System.MarshalByRefObject
{
// Fields
private ArrayList clients = new ArrayList(); // Names of clients
private String chatSession = ""; // Holds text for chat session
public void AddClient(string name)
{
if (name != null)
{
lock (clients)
{
clients.Add(name);
}
}
}
public void RemoveClient(String name)
{
lock (clients)
{
clients.Remove(name);
}
}
public void AddText(String newText)
{
if (newText != null)
{
lock (chatSession)
{
if (chatSession == "")
chatSession += newText;
else chatSession +=Environment.NewLine + newText;
}
}
}
public ArrayList Clients()
{
return clients;
}
public String ChatSession()
{
return chatSession;
}
}
}
protected override void OnStart(string[] args)
{
HttpChannel channel = new HttpChannel(12345);
ChannelServices.RegisterChannel(channel);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(ChatServerObject),
"ChatSeverAddress", WellKnownObjectMode.Singleton);
}
正如你所见,我们正在注册 ChatServerObject
类型的对象,该对象位于我们的 RemoteHello.dll 中。ChatServerAddress
是客户端用于定位服务的对象 URI。最后一个参数 WellKnownObjectMode.Singleton
需要一些解释。它定义了如何激活已知对象。
成员名称 | 描述 |
---|---|
单例 |
每个传入消息都由同一对象实例服务。 |
SingleCall |
每个传入消息都由新的对象实例服务。 |
由于我们希望与所有客户端共享我们的对象,因此我们将其设为单例。
现在,我们需要添加安装程序来安装此 Windows 服务。右键单击设计模式下的 Windows 服务,然后单击添加安装程序。这会将 ProjectInstaller.cs 添加到你的项目中。如果你转到此安装程序的设计模式,你将看到已经添加了两个控件:
设置这些控件的 DisplayName
、Description
、ServiceName
和 AccountType
等属性。此外,我们希望我们的服务在安装时处于启动模式。这可以通过添加 ServiceController
来实现。因此,像这样重写 PRojectInstaller
类中的 Install
函数:
public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
//Add the ServiceController so that my service
//will be in a start state as soon as it get installed.
ServiceController controller = new ServiceController("ChatService");
controller.Start();
}
完成此操作后,我们可以使用 InstallUtil 来安装我们的应用程序。因此,启动 Visual Studio 命令提示符。将路径更改为聊天服务的调试文件夹,然后使用以下命令:
InstallUtil ChatService.exe
你可以验证服务是否已正确安装。转到开始 -> 运行 -> Services.msc。查看你的聊天服务是否已安装。服务的名称将是你你在 projectInstaller 属性中指定的名称。
因此,现在我们已经运行了带有托管可远程对象的聊天服务器。
按照你喜欢的方式创建 GUI。我没有关注 GUI,但你可以随时使其看起来更好。以下几点需要注意:
HttpChannel channel = new HttpChannel();
ChannelServices.RegisterChannel(channel);
RemotingConfiguration.RegisterWellKnownClientType(
typeof(ChatServerObject), "https://:12345/ChatSeverAddress");
_chatServerObject = new ChatServerObject();
此表单上的其他控件的使用非常直接。同时,请确保在 IDE 外部运行 chatClient 应用程序,以便你可以运行多个客户端。开始登录,这将建立客户端与聊天服务器之间的连接,并创建可远程对象的代理。
历史
我将致力于创建一个更贴近实际的聊天应用程序,你可以与单个客户端聊天,而不是将文本广播给所有已连接的客户端。