跟我一起學WCF(2)——利用.NET Remoting技術開發分布式應用

一、引言

?  上一篇博文分享了消息隊列(MSMQ)技術來實現分布式應用,在這篇博文繼續分享下.NET平臺下另一種分布式技術——.NET Remoting。

二、.NET Remoting 介紹

2.1 .NET Remoting簡介

?  .NET REmoting與MSMQ不同,它不支持離線可得,另外只適合.NET平臺的程序進行通信。它提供了一種允許對象通過應用程序域與另一個對象進行交互的框架。.NET 應用程序都在一個主應用程序域中執行的,在一個應用程序域中的代碼不能訪問另一個應用程序域的數據,然而在某些情況下,我們需要跨應用程序域,與另外的應用程序域進行通信,這時候就可以采用.NET Remoting技術來實現與另一個程序域中的對象進行交互。

2.2 .NET Remoting基本原理

?  .NET Remoting技術是通過通道來實現兩個應用程序之間對象的通信的。首先,客戶端通過Remoting技術,訪問通道來獲得服務器端對象,再通過代理解析為客戶端對象,也稱作透明代理,此時獲得客戶端對象只是服務器對象的一個引用。這既保證了客戶端和服務端有關對象的松散耦合,同時優化了通信的性能。在這個過程中,當客戶端通過透明代理來調用遠程對象的方法時,此時會將調用封裝到一個消息對象中,該消息對象包括遠程對象信息,被調用的方法名和參數,然后透明代理會將調用委托給真實代理(RealProxy對象)的Invoke方法來生成一個IMethodCallMessage,接著通過序列化把這個消息對象序列化成數據流發送到通道,通道會把數據流傳送到服務器端。當服務器接收到經過格式化的數據之后,首先從中通過反序列化來還原消息對象,之后在服務器端來激活遠程對象,并調用對應的方法,而方法的返回結果過程則是按照之前的方法反向重復一遍,具體的實現原理圖如下所示:

2.3 .NET Remoting幾個重要概念

?  上面簡單介紹了下.NET Remoting實現分布式應用程序的基本原理,這里介紹下在.NET Remoting中涉及的幾個重要概念。

  1. 遠程對象:是運行在服務器端的對象,客戶端不能直接調用,由于.NET Remoting傳遞的對象是以引用的方式,因此所傳遞的遠程對象必須繼承MarshalByRefObject類,這個類可以使遠程對象在.NET Remoting應用通信中使用,支持對象的跨域邊界訪問。
  2. 遠程對象的激活方式:在訪問服務器端的一個對象實例之前,必須通過一個名為Activation的進程創建它并進行初始化。這種客戶端通過通道來創建遠程對象的方式稱為對象的激活。在.NET Remoting中,遠程對象的激活分為兩大類:服務器端激活和客戶端激活。
  • 服務器端激活,又叫做WellKnow(知名對象)激活模式,為什么稱為知名對象激活模式呢?是因為服務應用程序在激活對象實例之前會在一個眾所周知的統一資源標示符(URI)上發布這個類型,然后該服務器進行會為此類型配置一個WellKnow對象,并根據指定的端口或地址來發布對象。.NET Remoting把服務器端激活又分為SingleTon模式和SingleCall模式兩種。

  SingleTon模式:此為有狀態模式。如果設置為SingleTon激活模式,則.NET Remoting將為所有客戶端建立同一個對象實例。當對象處于活動狀態時,SingleTon實例會處理所有后來的客戶端訪問請求,而不管它們是同一個客戶端,還是其他客戶端。SingleTon實例將在方法調用中一直維護其狀態,類似static成員的概念

  SingleCall模式:是一種無狀態模式。一旦設置為SingleCall模式,則當客戶端調用遠程對象的方法時,Remoting會為每一個客戶端建立一個遠程對象實例,對象實例的銷毀則是由GC自動管理。類似實例成員的概念。

  • 客戶端激活:與Wellknow模式不同,。NET Remoting在激活每個對象實例的時候,會給每個客戶端激活的類型指派一個URI。客戶端激活模式一旦獲得客戶端的請求,將為每一個客戶端都建立一個實例引用。SingleCall模式與客戶端激活模式的區別有:首先,對象實例創建的時間不同。客戶端激活方式是客戶一旦發出調用請求就實例化,而SingleCall則要等到調用對象方法時再創建。其次,SingleCall模式激活的對象是無狀態的,對象聲明周期由GC管理,而客戶端激活的對象是有狀態的,其生命周期可自定義。第三,兩種激活模式在服務器端和客戶端實現的方法不一樣,尤其是在客戶端,SingleCall模式由GetObject()來激活,它調用對象默認的構造函數,而客戶端激活模式,則通過CreateInstance()來激活,它可以傳遞參數,所以可以調用自定義的構造函數來創建實例。

  3. 通道:在.NET Remoting中時通過通道來實現兩個應用程序域之間對象的通信。.NET Remoting中包括4中通道類型:

  1. TcpChannel:Tcp通道使用Tcp協議來跨越.Net Remoting邊界來傳輸序列化的消息流,TcpChannel默認使用二進制格式序列化消息對象,因此具有更高的傳輸性能,但不提供任何內置的安全功能。
  2. HttpChannel:Http通道使用Http協議在客戶端和服務器之間發生消息,使其在Internet上穿越防火墻來傳輸序列化的消息流(這里準確講不能說穿越,主要是因為防火墻都開放了80端口,所以使用Http協議可以穿過防火墻進行數據的傳輸,如果防火墻限制了80端口,Http協議也照樣不能穿越防火墻)。默認情況下,HttpChannel使用Soap格式序列化消息對象,因此它具有更好的互操作性,并且可以使用Http協議中的加密機制來對消息進行加密來保證安全性。因此,通常在局域網內,我們更多地使用TcpChannel,如果要穿越防火墻,則使用HttpChannel。
  3. IpcChannel:進程間通信,只使用同一個系統進程之間的通信,不需要主機名和端口號。而使用Http通道和Tcp通道都要指定主機名和端口號。
  4. 自定義通道:自定義的傳輸通道可以使用任何基本的傳輸協議來進行通信,如UDP協議、SMTP協議等。

三、利用.NET Remoting技術開發分布式應用三部曲

?  前面詳細介紹了.NET Remoting相關內容,下面具體看看如何使用.NET Remoting技術來開發分布式應用程序。開發.NET Remoting應用分三步走。

第一步:創建遠程對象,該對象必須繼承MarshalByRefObject對象。具體的示例代碼如下:

 1 namespace RemotingObject
 2 {
 3     // 第一步:創建遠程對象
 4     // 創建遠程對象——必須繼承MarshalByRefObject,該類支持對象的跨域邊界訪問
 5     public class MyRemotingObject :MarshalByRefObject
 6     {
 7         // 用來測試Tcp通道 
 8         public int AddForTcpTest(int a, int b)
 9         {
10             return a + b;
11         }
12 
13         // 用來測試Http通道
14         public int MinusForHttpTest(int a, int b)
15         {
16             return a - b;
17         }
18 
19         // 用來測試IPC通道
20         public int MultipleForIPCTest(int a, int b)
21         {
22             return a * b;
23         }
24     }
25 }

  遠程對象分別定義3個方法,目的是為了測試3中不同的通道方式的效果。

第二步:創建服務器端,需要添加System.Runtime.Remoting.dll引用,具體實現代碼如下所示:

 1 using System;
 2 using System.Runtime.Remoting;
 3 using System.Runtime.Remoting.Channels;
 4 using System.Runtime.Remoting.Channels.Http;
 5 using System.Runtime.Remoting.Channels.Ipc;
 6 using System.Runtime.Remoting.Channels.Tcp;
 7 
 8 namespace RemotingServerHost
 9 {
10     // 第二步:創建宿主應用程序
11     class Server
12     {
13         static void Main(string[] args)
14         {
15             // 1.創建三種通道
16 
17             // 創建Tcp通道,端口號9001
18             TcpChannel tcpChannel = new TcpChannel(9001);
19             
20             // 創建Http通道,端口號9002
21             HttpChannel httpChannel = new HttpChannel(9002);
22 
23             // 創建IPC通道,端口號9003
24             IpcChannel ipcChannel = new IpcChannel("IpcTest");
25 
26             // 2.注冊通道
27             ChannelServices.RegisterChannel(tcpChannel, false);
28             ChannelServices.RegisterChannel(httpChannel, false);
29             ChannelServices.RegisterChannel(ipcChannel, false);
30 
31             // 打印通道信息
32             // 打印Tcp通道的名稱
33             Console.WriteLine("The name of the TcpChannel is {0}", tcpChannel.ChannelName);
34             // 打印Tcp通道的優先級
35             Console.WriteLine("The priority of the TcpChannel is {0}", tcpChannel.ChannelPriority);
36 
37             Console.WriteLine("The name of the HttpChannel is {0}", httpChannel.ChannelName);
38             Console.WriteLine("The priority of the httpChannel is {0}", httpChannel.ChannelPriority);
39 
40             Console.WriteLine("The name of the IpcChannel is {0}", ipcChannel.ChannelName);
41             Console.WriteLine("The priority of the IpcChannel is {0}", ipcChannel.ChannelPriority);
42 
43             // 3. 注冊對象
44             // 注冊MyRemotingObject到.NET Remoting運行庫中
45             RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemotingObject.MyRemotingObject), "MyRemotingObject", WellKnownObjectMode.Singleton);
46             Console.WriteLine("Press any key to exit");
47             Console.ReadLine();
48         }
49     }
50 }

第三步:創建客戶端程序,具體的實現代碼如下所示:

 1 using RemotingObject;
 2 using System;
 3 
 4 namespace RemotingClient
 5 {
 6     class Client
 7     {
 8         static void Main(string[] args)
 9         {
10             // 使用Tcp通道得到遠程對象
11             //TcpChannel tcpChannel = new TcpChannel();
12             //ChannelServices.RegisterChannel(tcpChannel, false);
13             MyRemotingObject proxyobj1 = Activator.GetObject(typeof(MyRemotingObject), "tcp://localhost:9001/MyRemotingObject") as MyRemotingObject;
14             if (proxyobj1 == null)
15             {
16                 Console.WriteLine("連接TCP服務器失敗");
17             }
18 
19             //HttpChannel httpChannel = new HttpChannel();
20             //ChannelServices.RegisterChannel(httpChannel, false);
21             MyRemotingObject proxyobj2 = Activator.GetObject(typeof(MyRemotingObject), "http://localhost:9002/MyRemotingObject") as MyRemotingObject;
22             if (proxyobj2 == null)
23             {
24                 Console.WriteLine("連接Http服務器失敗");
25             }
26 
27             //IpcChannel ipcChannel = new IpcChannel();
28             //ChannelServices.RegisterChannel(ipcChannel, false);
29             MyRemotingObject proxyobj3 = Activator.GetObject(typeof(MyRemotingObject), "ipc://IpcTest/MyRemotingObject") as MyRemotingObject;
30             if (proxyobj3 == null)
31             {
32                 Console.WriteLine("連接Ipc服務器失敗");
33             }
34             // 輸出信息
35             Console.WriteLine("This call object by TcpChannel, 100 + 200 = {0}", proxyobj1.AddForTcpTest(100, 200));
36             Console.WriteLine("This call object by HttpChannel, 100 - 200 = {0}", proxyobj2.MinusForHttpTest(100, 200));
37             Console.WriteLine("This call object by IpcChannel, 100 * 200 = {0}", proxyobj1.MultipleForIPCTest(100, 200));
38             Console.WriteLine("Press any key to exit!");
39             Console.ReadLine();
40         }
41     }
42 }

  經過上面的三步,我們就完成了這個分布式應用的開發工作,下面測試下該程序是否可以正常運行,首先,運行服務器端,你將看到如下界面:

  在.NET Remoting中,是允許同時創建多個通道的,但是.NET Remoting要求通道的名字必須不同,因為名字是用來標識通道的唯一標識符。但上面代碼中,我們并沒有指明通道的名字,為什么還可以允許成功呢?從上面圖片可知,當我們創建通道時,如果沒有為其顯式指定通道名,則會使用對應的通道類型作為該通道名,如TcpChannel將會以tcp作為通道名,如果想注冊多個Tcp通道則必須顯式指定其名字。

  下面看看運行客戶端所獲得的結果,具體客戶端運行效果如下圖所示:

?四、使用配置文件來重寫上面的分布式程序

  在第三部分中,我們是把服務器的各種通道方式和地址寫死在程序中的,這樣的實現方式部署起來不方便,下面使用配置文件的方式來配置服務器端的通道類型和服務器地址。  遠程對象的定義不需要改變,下面直接看服務器端使用配置文件后的實現代碼如下所示:

 1 using System;
 2 using System.Runtime.Remoting;
 3 using System.Runtime.Remoting.Channels;
 4 
 5 namespace RemotingServerHostByConfig
 6 {
 7     class Program
 8     {
 9         static void Main(string[] args)
10         {
11             RemotingConfiguration.Configure("RemotingServerHostByConfig.exe.config", false);
12 
13             foreach (var channel in ChannelServices.RegisteredChannels)
14             {
15                 // 打印通道的名稱
16                 Console.WriteLine("The name of the Channel is {0}", channel.ChannelName);
17                 // 打印通道的優先級
18                 Console.WriteLine("The priority of the Channel is {0}", channel.ChannelPriority);
19             }
20             Console.WriteLine("按任意鍵退出……");
21             Console.ReadLine();
22         }
23     }
24 }

  服務端的配置文件的內容為:

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <!--服務端App.config的內容-->
 3 <configuration>
 4     <startup> 
 5         <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
 6     </startup>
 7   <system.runtime.remoting>
 8     <application>
 9       <service>
10         <wellknown  mode="Singleton"
11                     type="RemotingObject.MyRemotingObject,RemotingObject"
12                     objectUri="MyRemotingObject"/>
13       </service>
14       <channels>
15         <channel port="9001" ref="tcp"/>
16         <channel port="9002" ref="http"/>
17         <channel portName="IpcTest" ref="ipc"/> <!--Ipc通道不需要端口號-->
18       </channels>
19     </application>
20   </system.runtime.remoting>
21 </configuration>

  此時,客戶端程序的實現代碼如下所示:

 1 using RemotingObject;
 2 using System;
 3 using System.Runtime.Remoting;
 4 
 5 namespace RemotingClientByConfig
 6 {
 7     class Program
 8     {
 9         static void Main(string[] args)
10         {
11             //使用HTTP通道得到遠程對象
12             RemotingConfiguration.Configure("RemotingClientByConfig.exe.config", false);
13             MyRemotingObject proxyobj1 = new MyRemotingObject();
14             if (proxyobj1 == null)
15             {
16                 Console.WriteLine("連接服務器失敗");
17             }
18 
19             Console.WriteLine("This call object by TcpChannel, 100 + 200 = {0}", proxyobj1.AddForTcpTest(100, 200));
20             Console.WriteLine("This call object by HttpChannel, 100 - 200 = {0}", proxyobj1.MinusForHttpTest(100, 200));
21             Console.WriteLine("This call object by IpcChannel, 100 * 200 = {0}", proxyobj1.MultipleForIPCTest(100, 200));
22             Console.WriteLine("Press any key to exit!");
23             Console.ReadLine();
24         }
25     }
26 }

  客戶端配置文件為:

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <configuration>
 3     <startup> 
 4         <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
 5     </startup>
 6   <system.runtime.remoting>
 7     <application>
 8       <client>
 9         <wellknown  type="RemotingObject.MyRemotingObject,RemotingObject"
10                     url="http://localhost:9002/MyRemotingObject" />
11       </client>
12       <channels>    
13         <channel ref="tcp" port="0"></channel>
14         <channel ref="http" port="0"></channel>
15         <channel ref="ipc" port="0"></channel>
16       </channels>
17     </application>
18   </system.runtime.remoting>
19 </configuration>

  使用配置文件修改后的分布式程序的運行結果與前面的運行結果一樣,這里就不一一貼圖了。

五、總結

?  到這里,.NET Remoting技術的分享就結束了,本文只是對.NET Remoting技術做了一個基本的介紹,如果想深入了解.NET Remoting技術的話,推薦大家可以看看下面的專題細細品味C#——.Net Remoting專題。在下一篇文章中,繼續為大家分享另一種分布式技術——Web Service。

  ?本文的示例代碼文件下載:.NETRemotingSample

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/276326.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/276326.shtml
英文地址,請注明出處:http://en.pswp.cn/news/276326.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

二叉樹的建立與遍歷_51、二叉樹遍歷-重建二叉樹JZ4

題目描述輸入某二叉樹的前序遍歷和中序遍歷的結果&#xff0c;請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重復的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6}&#xff0c;則重建二叉樹并返回。思路回顧三種經典的遍歷&…

越來越覺得現在的工作很枯燥

很不想這么說&#xff0c;但又不想欺騙自己&#xff0c;真的是很枯燥&#xff0c;不過這種感覺早在一年在在上一間公司時就很強烈的有過這種感覺了&#xff0c;只不過現在是又一次有感觸罷了。話說說我這種性質的工作枯燥很多人都講過&#xff0c;如果哪個人說不枯燥估計腦袋進…

推薦關注這7個高質量的前端公眾號

拓寬眼界&#xff0c;增加深度&#xff0c;在閱讀的世界里&#xff0c;我們往往能找到不一樣的態度&#xff0c;提升朋友圈質量&#xff0c;從關注這幾個公眾號開始。輕掃一下二維碼就行了&#xff0c;你可以試試&#xff0c;肯定會有意外收獲。大遷世界 簡介&#xff1a;前端小…

MySQL 實用語句集合

MySQL 實用語句集合 參考鏈接[用戶]&#xff1a;http://blog.csdn.net/dmtnewtons_blog/article/details/9136339 參考鏈接[屬性]&#xff1a;http://stackoverflow.com/questions/15821532/get-current-auto-increment-value-for-any-table 參考鏈接[索引]&#xff1a;htt…

python對象序列化或持久化的方法

http://blog.csdn.net/chen_lovelotus/article/details/7233293 一、Python對象持久化方法 目前為止&#xff0c;據我所知&#xff0c;在python中對象持久化有以下幾種方法&#xff1a; 1. 使用(dbhash/bsddb, dbm, gdbm, dumbdbm 等&#xff09;以及它們的"管理器"(…

Windows Live Writer 在win2003 的安裝方法

下載Windows Live Writer整體安裝包&#xff0c;最好是離線安裝包 2.在xp系統上安裝 3.查找C:\Program Files\Common Files\Windows Live\.cache目錄 .cache目錄是隱藏的&#xff0c;目錄下面就是各個安裝文件的msi安裝包 4.拷貝相應的msi文件&#xff0c;到Windows 2003安裝就…

decode 大于比較 小于_6 燃氣輸配系統6.3 壓力不大于1.6Mpa的室外燃氣管道城鎮燃氣設計規范 GB500282006(2020修訂版)...

6.3 壓力不大于1.6Mpa的室外燃氣管道6.3.1中壓和低壓燃氣管道宜采用聚乙烯管、機械接口球墨鑄鐵管、鋼管或鋼骨架聚乙烯塑料復合管&#xff0c;并應符合下列要求&#xff1a; 1 聚乙烯燃氣管應符合現行的國家標準《燃氣用埋地聚乙烯管材》GB15558.1 和《燃氣用埋地聚乙烯管件…

若川的2017年度總結,一如既往

可以點擊上方的標簽若川的故事、年度總結&#xff0c;查看往期文章有讀者反饋說看我年度總結系列比我源碼系列更有啟發。所以打算把2016-2018的年度總結發布到公眾號聲明原創&#xff0c;希望對大家有所啟發。&#xff08;雖然我的每一年都過得非常普通...&#xff09;若川的20…

MIME協議及源郵件格式分析

轉載鏈接&#xff1a;http://wenku.baidu.com/view/7246de671ed9ad51f01df277.html 電子郵件也許是一個Internet上的流行最廣泛的應用。也是我們現在的大多數網絡辦公流程的基礎。各種郵件服務器很多,但都大都遵循以1982年出版的RFC822--《ARPA網絡文本信息格式標準(STANDARD F…

溝通:用故事產生共鳴

《溝通:用故事產生共鳴》(全彩) 基本信息作者&#xff1a; Nancy Duarte(南希.杜瓦特)譯者&#xff1a; 馮海洋出版社&#xff1a;電子工業出版社ISBN&#xff1a;9787121195914上架時間&#xff1a;2013-4-1出版日期&#xff1a;2013 年3月開本&#xff1a;12開頁碼&#xff1…

合工大五套卷_2020合工大超越數一五套卷第一套感想

合工大的卷子確實不錯&#xff0c;題目給我的感覺是題干包裝的看起來就很難&#xff0c;但是寫起來還是一樣的套路。計算上要難一些&#xff0c;需要細心點選擇題:1.可去間斷點的定義和泰勒公式2.這個題我用排除法寫的&#xff0c;可微的話連續和偏導存在都成立了&#xff0c;然…

DotNet關鍵知識點——WPF篇(一)(范德成編輯批注版)

1. Journal 的使用 Journal 用于在 XAML 瀏覽器應用程序&#xff08;XBAP&#xff09;中維護歷史訪問頁。刪除前一訪問頁只需調當前 NavigationService 對象的 RemoveBackEntry() 即可&#xff1b;而增加一個訪問頁則復雜得多&#xff1a; 1) 實現一個 CustomContentState 的派…

若川的2018年度總結,平淡無奇

可以點擊上方的標簽若川的故事、年度總結&#xff0c;查看往期文章偷偷告訴你&#xff0c;公眾號內回復【報告】&#xff0c;可以獲取你自己的github 2020 年度報告昨晚在我的6個微信群里都發了紅包&#xff0c;以這樣的方式跨過了2020年。運營公眾號真的挺難的&#xff0c;比如…

Simple TCP Server Client Socket C

轉載鏈接&#xff1a;http://blog.163.com/caipeipei_love126/blog/static/2596603220101118433940/ tcpserver.c #include<stdlib.h> #include<stdio.h> #include<errno.h> #include<string.h> #include<netdb.h> #include<sys/types.h>…

基于dnn的車牌識別_自然場景中文文字識別,身份證火車票都能識別

圖像處理中OCR(Optical Character Recognition光學字符識別)場景非常多&#xff0c;也給大家的工作生活帶來了很多便利&#xff0c;比如車牌識別就能管理停車場車輛的出入&#xff0c;快遞時只需給一個帶有快遞信息的圖就能自動解析上傳發件信息和收件信息&#xff0c;再比如我…

年末的大廠前端面試總結(20屆雙非二本)-終入字節

關注若川視野, 回復"pdf" 領取資料&#xff0c;回復"1"&#xff0c;可加群長期交流學習自我介紹雙非二本,軟件工程,自學前端,今年畢業。喜歡編程,古風,日語和英語。常以冷月心之名混跡前端江湖,也曾在混跡網文圈時用冷月心做筆名簽約掌閱,作品《清起風云》…

面試題(轉的)

第一組   1.燒一根不均勻的繩&#xff0c;從頭燒到尾總共需要1個小時。現在有若干條材質相同的繩子&#xff0c;問如何用燒繩的方法來計時一個小時十五分鐘呢?  2.你有一桶果凍&#xff0c;其中有黃色、綠色、紅色三種&#xff0c;閉上眼睛抓取同種顏色的兩個。抓取多少個…

python三酷貓_洛克王國三代酷貓登場 冰水酷貓解析

洛克王國三代酷貓登場 冰水酷貓解析 洛克王國三代武斗酷貓解析三代水靈&#xff0c;在哥斯拉的傾情推薦下&#xff0c;小洛克們都已經很熟悉了吧&#xff01;那和水靈同一期出現的帥哥——武斗酷貓&#xff0c;如果三代遺傳了&#xff0c;會怎么樣呢&#xff1f;小洛克們一起來…

Linux禁止用戶登錄

轉載鏈接&#xff1a;http://blog.sina.com.cn/s/blog_4cebadd10100a9bl.html 我們在做系統維護的時候&#xff0c;希望個別用戶或者所有用戶不能登錄系統&#xff0c;保證系統在維護期間正常運行。這個時候我們就要禁止用戶登錄。 1、禁止個別用戶登錄。比如禁止lynn用戶登錄…