当前位置: 首页 > 编程日记 > 正文

Flex与.NET互操作(十二):FluorineFx.Net的及时通信应用(Remote Shared Objects)(三)

远程共享对象(Remote Shared Objects) 可以用来跟踪、存储、共享以及做多客户端的数据同步操作。只要共享对象上的数据发生了改变,将会把最新数据同步到所有连接到该共享对象的应用程序客户端。FluorineFx所提供的远程共享对象(Remote Shared Objects)和FMS的共享对象的功能是一样,对于熟悉FMS开发的朋友来说,学习FluorineFx的远程共享对象是非常简单的。
共享对象可以在服务器端创建,也可以在客户端创建。在客户端创建共享对象的方法和使用FMS开发是一样的,创建一个NetConnection对象,通过该对象的connect()方法连接到服务器,然后通过SharedObject.getRemote()方法就可以在客户端创建一个远程共享对象。如下实例代码:
private function connectionServer():void
{
    var nc:NetConnection 
= new NetConnection();
    nc.connect(
"rtmp://localhost:1617/SOAPP","username","password")
    nc.addEventListener(NetStatusEvent.NET_STATUS,onStatusHandler);
    nc.client 
= this;
}

private function onStatusHandler(event:NetStatusEvent):void
{
    
if(event.info.code == "NetConnectin.Connect.Success")
    {
        createSharedObject();
    }
}

private function createSharedObject():void
{
    var so:SharedObject 
= SharedObject.getRemote("OnLineUsers",nc.uri,false);
    so.addEventListener(SyncEvent.SYNC,onSyncHandler);
    so.connect(
this.nc);
    so.client 
= this;
}

private function onSyncHandler(event:SyncEvent):void
{
  
//..do other
}
在FluorineFx的服务器端创建远程共享对象和FMS有很大的区别,FluorineFx的ISharedObjectService接口提供了专门用于创建远程共享对象的方法CreateSharedObject(),ApplicationAdapter实现了此接口方法。定义如下:
public bool CreateSharedObject(IScope scope, string name, bool persistent)
{
      ISharedObjectService service 
= (ISharedObjectService)ScopeUtils.GetScopeService(scope, typeof(ISharedObjectService));
      
return service.CreateSharedObject(scope, name, persistent);
}
如果要在服务器端创建远程共享对象,直接调用ApplicationAdapter类中的CreateSharedObject()方法就可以。如下在FluorineFx服务器端创建远程共享对象的代码块:
ISharedObject users_so = GetSharedObject(connection.Scope, "OnLineUsers");
if (users_so == null)
{
       
//创建共享对象
        CreateSharedObject(connection.Scope, "OnLineUsers"false);
        users_so 
= GetSharedObject(connection.Scope, "OnLineUsers");
}
要想更新共享对象里的数据客户端还是使用setProperty()方法,而FluorineFx的服务器更新共享对象的方法则与FMS不一样,使用的是FluorineFx.Messaging.Api.IAttributeStore接口提供的SetAttribute()和RemoveAttribute()方法来更新共享对象里的数据。
陆续介绍了这么多,下面通过一个案例来看看该这么去应用远程共享对象。比如做IM、视频聊天、视频会议等及时通信类型的应用中,用户上线下线的频率非常高,这时候我们就可以使用远程共享对象去做在线用户的数据同步。
首先建立FluorineFx服务库,并建立一个应用类继承于ApplicationAdapter,通过重写ApplicationAdapter的相关方法来实现应用程序的不同需求,详细如下代码块:
using System;
using System.Collections.Generic;
using System.Text;
using FluorineFx.Messaging.Adapter;
using FluorineFx;
using FluorineFx.Messaging.Api;
using System.Diagnostics;
using FluorineFx.Messaging.Api.SO;
using FluorineFx.Exceptions;
using FluorineFx.Context;
using FluorineFx.Messaging.Api.Service;
using System.Collections;
using Fx.Adapter.DTO;

namespace Fx.Adapter
{
    
/// <summary>
    
/// 自定义ApplicationAdapter
    
/// </summary>
    [RemotingService]
    
public class MyApp : ApplicationAdapter
    {
        
/// <summary>
        
/// 应用程序启动
        
/// </summary>
        
/// <param name="application"></param>
        
/// <returns></returns>
        public override bool AppStart(IScope application)
        {
            Trace.WriteLine(
"应用程序启动");
            
return true;
        }

        
/// <summary>
        
/// 房间启动
        
/// </summary>
        
/// <param name="room"></param>
        
/// <returns></returns>
        public override bool RoomStart(IScope room)
        {
            Trace.WriteLine(
"房间启动");
            
if (!base.RoomStart(room))
                
return false;
            
return true;
        }

        
/// <summary>
        
/// 接收客户端的连接
        
/// </summary>
        
/// <param name="connection"></param>
        
/// <param name="parameters"></param>
        
/// <returns></returns>
        public override bool AppConnect(IConnection connection, object[] parameters)
        {
            
string userName = parameters[0as string;
            
string password = parameters[1as string;

            
if (password == null || password == string.Empty)
                
throw new ClientRejectedException(null);

            connection.Client.SetAttribute(
"userName", userName);
            
//获取共享对象(OnLineUsers)
            ISharedObject users_so = GetSharedObject(connection.Scope, "OnLineUsers");
            
if (users_so == null)
            {
                
//创建共享对象
                CreateSharedObject(connection.Scope, "OnLineUsers"false);
                users_so 
= GetSharedObject(connection.Scope, "OnLineUsers");
            }
            
//更新共享对象
            users_so.SetAttribute(userName, userName);
            
return true;
        }

        
/// <summary>
        
/// 加入房间
        
/// </summary>
        
/// <param name="client"></param>
        
/// <param name="room"></param>
        
/// <returns></returns>
        public override bool RoomJoin(IClient client, IScope room)
        {
            Trace.WriteLine(
"加入房间 " + room.Name);
            
return true;
        }

        
/// <summary>
        
/// 离开房间
        
/// </summary>
        
/// <param name="client"></param>
        
/// <param name="room"></param>
        public override void RoomLeave(IClient client, IScope room)
        {
            Trace.WriteLine(
"离开房间 " + room.Name);
            
base.RoomLeave(client, room);
        }

        
/// <summary>
        
/// 用户退出
        
/// </summary>
        
/// <param name="connection"></param>
        public override void AppDisconnect(IConnection connection)
        {
            
string userName = connection.Client.GetAttribute("userName"as string;
            ISharedObject users_so 
= GetSharedObject(connection.Scope, "OnLineUsers");
            
if (users_so != null)
            {
                
//从共享对象中移除当前退出系统用户
                users_so.RemoveAttribute(userName);
            }
            
base.AppDisconnect(connection);
        }
    }
}
开发好了ApplicationAdapter,还需要对此ApplicationAdapter进行通信配置,在FluorineFx的应用程序目录中添加app.config并进行如下配置:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
    
<application-handler type="Fx.Adapter.MyApp"/>
</configuration>
另外还需要配置一个客户端方法的通信通道,通过FluorineFx网站下的WEB-INF/flex/service-config.xml配置:
<?xml version="1.0" encoding="utf-8" ?>
<services-config>
      <channels>
          <channel-definition id="my-rtmp" class="mx.messaging.channels.RTMPChannel">
               
<endpoint uri="rtmp://{server.name}:1617" class="flex.messaging.endpoints.RTMPEndpoint"/>
          </channel-definition>
      </channels>
</services-config>
如上便完成了服务器端的开发,在flash/felx客户端通过NetConnection去连接应用,并根据当前的连接去连接服务器端的远程共享对象,最后通过异步事件来实现数据同步更新。如下程序运行截图:
此时开多个浏览器窗口测试,不同窗口使用不同的用户名登录,可以很清楚的看到,我们已经实现了在线用户的数据同步功能,可以及时的反映用户上线离线,可以及时的同步在线用户列表的数据。
另外远程共享对象还有一个功能非常强大的特性方法,就是连接到共享对象的客户端之间可以直接广播消息(客户端调用客户端的方法)。就以上面在线用户的案例为例,用户成功登陆服务器我需要广播一条消息,用户退出了我也需要广播一条消息,要实现这个功能就需要通过远程共享的客户端呼叫(send()方法)来实现,如下代码块:
private function onCallClient(message:String):void
{
    so.send(
"onSayMessage",message);
}
远程共享对象的send()方法调用了onSayMessage这个客户端方法来实现对连接到共享对象上的所有客户端广播消息,那么我们的在定义一个onSayMessage方法,如下:
/**
 * 接受客户端呼叫---此方法必须是public修饰
 
*/
public function onSayMessage(message:Object):void
{
    traceWriteln(message.toString());
}
private function traceWriteln(param:String):void
{
   txtTraceArea.htmlText += param + "\n";
   txtTraceArea.validateNow();
   txtTraceArea.verticalScrollPosition = txtTraceArea.maxVerticalScrollPosition;
}
如果想实现用户退出广播,可以通过服务器端RPC的方法调用客户端的方法来实现,关于RPC请查看《Flex与.NET互操作(十一):基于FluorineFx.Net的及时通信应用(Remote Procedure Call)(二) 》有详细介绍。下面是Flex客户端的完整代码:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"  
    width
="530" height="378" backgroundGradientAlphas="[1.0, 1.0]" 
    backgroundGradientColors
="[#000000, #686868]" fontSize="12">
    
<mx:Script>
        
<![CDATA[
            import mx.controls.Alert;
            import dotnet.fluorinefx.VO.UserInfo;
            
            
private var nc:NetConnection;
            
private var so:SharedObject;
            
private var info:UserInfo;
            
            
private function connectionServer(event:MouseEvent):void
            {
                info 
= new UserInfo();
                info.UserName 
= this.txtUserName.text;
                info.Password 
= this.txtPassword.text;
                
                nc 
= new NetConnection();
                nc.connect(
"rtmp://localhost:1617/SOAPP",info.UserName,info.Password);
                nc.addEventListener(NetStatusEvent.NET_STATUS,onStatusHandler);
                nc.client 
= this;
                
                
this.txtUserName.text="";
                
this.txtPassword.text="";
                
this.txtUserName.setFocus();
            }
            
            
private function onStatusHandler(event:NetStatusEvent):void
            {
                
this.connStatus.text = "连接状态:" + event.info.code;
                
if(event.info.code == "NetConnection.Connect.Success")
                {
                    
//连接远程共享对象
                    so = SharedObject.getRemote("OnLineUsers",nc.uri,false);
                    
if(so)
                    {
                        so.addEventListener(SyncEvent.SYNC,onSyncHandler);
                        so.connect(nc);
                        so.client 
= this;
                    }
                    onCallClient(
"用户【 <font color=\"#4100b9\">"+info.UserName+"</font>】登陆了系统!");
                }
            }
            
            
private function onSyncHandler(event:SyncEvent):void
            {
                var temp:Array 
= new Array();
                
for(var u:String in so.data)
                {
                    
//traceWriteln("异步事件->共享对象:" + u + ":" + so.data[u]);
                    temp.push(so.data[u]);
                }
                
this.userList.dataProvider = temp;
            }
            
            
private function traceWriteln(param:String):void
            {
                txtTraceArea.htmlText 
+= param + "\n";
                txtTraceArea.validateNow();
                txtTraceArea.verticalScrollPosition 
= txtTraceArea.maxVerticalScrollPosition;
            }
            
            
private function onCallClient(message:String):void
            {
                so.send(
"onSayMessage",message);
            }
            
/**
             * 接受客户端呼叫
             
*/
            
public function onSayMessage(message:Object):void
            {
                traceWriteln(message.toString());
            }
        ]]
>
    
</mx:Script>
    
<mx:Label x="24" y="134" id="connStatus" width="288" color="#FFFFFF"/>
    
<mx:List x="342" y="10" height="347" width="160" id="userList" >
    
</mx:List>
    
<mx:Form x="24" y="10" width="236">
        
<mx:FormItem label="用户名:" color="#FFFFFF">
            
<mx:TextInput id="txtUserName" width="130" color="#000000"/>
        
</mx:FormItem>
        
<mx:FormItem label="密  码:" color="#FFFFFF">
            
<mx:TextInput id="txtPassword" width="130" 
                color
="#000000" displayAsPassword="true"/>
        
</mx:FormItem>
        
<mx:FormItem label="">
            
<mx:Button label="登陆服务器" click="connectionServer(event)" 
                enabled
="{this.txtUserName.text.length&gt;0?true:false}" color="#FFFFFF"/>
        
</mx:FormItem>
    
</mx:Form>
    
<mx:TextArea x="24" y="174" width="288" height="153" alpha="1.0" 
        backgroundColor
="#F2D2D2" backgroundAlpha="0.26" color="#FFFFFF" 
        id
="txtTraceArea" borderColor="#FFFFFF"/>
</mx:Application>

相关文章:

ffmpeg api的应用——提取视频图片

这些年来&#xff0c;“短视频”吸引了无数网民的注意。相对于丰富有趣的内容&#xff0c;我们码农可能更关心其底层技术实现。本系列文章将结合ffmpeg&#xff0c;讲解几则视频处理案例。&#xff08;转载请指明出于breaksoftware的csdn博客&#xff09; “短视频”都是以“文…

蚂蚁金服AAAI论文:基于长短期老师的样本蒸馏方法和自动车险定损系统的最新突破...

来源 | 蚂蚁金服出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;一年一度在人工智能方向的顶级会议之一AAAI 2020于2月7日至12日在美国纽约举行&#xff0c;旨在汇集世界各地的人工智能理论和领域应用的最新成果。以下是蚂蚁金服的技术专家对入选论文《基于长短期老师…

C# 实现HTML转换成图片的方法

/// <summary> /// 通过WebBrowser控件来实现从HTML到Bmp图片的生成。 /// </summary> /// <param name"htmPath">HTML路径</param> /// <returns>Bmp图片路径</returns> private static st…

一套使用注入和Hook技术托管入口函数的方案

工作中&#xff0c;我们可能会经常使用开源项目解决一些领域中的问题。这种“拿来主义”是一种“专业人干专业事”的思想&#xff0c;非常实用。&#xff08;转载请指明出于breaksoftware的csdn博客&#xff09; 一般场景下&#xff0c;我们都是把开源项目代码编译到我们自己的…

微软发布虚机管理SCVMM 2008 R2 RC版

来源&#xff1a;IT168服务器频道近日&#xff0c;微软发布了SCVMM&#xff08;系统中心虚拟机管理器&#xff0c;System Center Virtual Machine Manager&#xff09;2008 R2的RC版本。据了解&#xff0c;新的SCVMM相比去年的版本增加了六大新功能&#xff0c;目前用户可以从W…

AI芯片行业发展的来龙去脉

作者 | 清华大学微电子学研究所尹首一来源 | 《微纳电子与智能制造》期刊引言人 工 智 能( aritificial intelligence &#xff0c;AI )是 一 门融合了数学 、计算机科学 、统计学 、脑神经学和社会科学 的前沿综合性技术。它的目标是希望计算机可以像 人一样思考 &#xff0c;…

8)排序②排序算法之选择排序[1]直接选择排序

1 #include<iostream>2 using namespace std;3 4 //*******直接选择排序*********5 int select_sort(int n,int array[100]){6 int i,j;7 for(i0;i<n;i){8 for(ji;j<n;j){9 if(array[i]>array[j]){ 10 int temparr…

一份招聘需求的分析

今早&#xff0c;长期合作伙伴又给我们一份招聘需求&#xff0c;以下是招聘条件&#xff1a; 工作性质&#xff1a;全职 工作地点&#xff1a;南京 发布日期&#xff1a;2009/6/15 截止日期&#xff1a;2009/6/30 招聘人数&#xff1a;6 工作经验&#xff1a;不限 学  历&…

bug诞生记——隐蔽的指针偏移计算导致的数据错乱

C语言为了兼容C语言&#xff0c;做了很多设计方面的考量。但是有些兼容设计产生了不清晰的认识。本文就将讨论一个因为认知不清晰而导致的bug。&#xff08;转载请指明出于breaksoftware的csdn博客&#xff09; class Base { public:Base() default;void set_v_b(int v_b) {_…

福利直投!这个活动承包你2020全年技术干货

CSDN技术公开课有奖评选开始啦~~听过课的小伙伴们&#xff0c;哪位讲师的分享让你获益匪浅&#xff1f;记得给TA投票哦&#xff01;投票后获取入群方式&#xff0c;参与抽奖&#xff0c;奖品很丰厚哦~~进入付费时代&#xff0c;如今我们看似只要招招手&#xff0c;一切知识随手…

第四章 Controller接口控制器详解(5)——跟着开涛学SpringMVC

2019独角兽企业重金招聘Python工程师标准>>> 原创内容&#xff0c;转载请注明iteye http://jinnianshilongnian.iteye.com/ 4.15、MultiActionController 之前学过的控制器如AbstractCommandController、SimpleFormController等一般对应一个功能处理方法&#xff…

自动机器学习:团队如何在自动学习项目中一起工作?(附链接)

来源 | 数据派THU作者 | Francesca Lazzeri翻译 | 王琦责编 | Carol出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;去年11月&#xff0c;我写了一篇关于使用自动机器学习来进行AI民主化&#xff08;democratization&#xff09;的文章&#xff08;见下面链接&#x…

C++拾趣——STL容器的插入、删除、遍历和查找操作性能对比(ubuntu g++)——插入

操作系统是ubuntu 18.04.1 server amd64&#xff0c;gcc是 7.3.0。编译产出是64位测试程序。&#xff08;转载请指明出于breaksoftware的csdn博客&#xff09; 因为加入测量&#xff0c;就会导致误差。我已经尽量将环境影响降低&#xff0c;但是还是难免有误差。大家可以通过文…

SSIS中的记录集目标

这一篇&#xff0c;我们来看看另外一个特殊的目标组件&#xff1a;记录集目标。它与DataReader目标有些类似&#xff0c;也是在内存中的。但与DataReader目标不同的是&#xff0c;它可以被下游任务使用。 它的使用也比较简单&#xff0c;我们一般指定一个变量来接收它的结果&am…

Leetcode: Maximum Depth of Binary Tree

题目&#xff1a;算出二叉树的最大深度 解决方案&#xff1a;&#xff08;1&#xff09;BFS &#xff08;2&#xff09;DFS (1)BFS 一层一层往下搜索&#xff0c;一直找到最深的点&#xff0c;这里由于节点的val是没有用的&#xff0c;所以可以用来存储当前节点的深度&#xff…

C++拾趣——STL容器的插入、删除、遍历和查找操作性能对比(ubuntu g++)——删除

相关环境和说明在《C拾趣——STL容器的插入、删除、遍历和查找操作性能对比&#xff08;ubuntu g&#xff09;——插入》已给出。本文将分析从头部、中间和尾部对各个容器进行删除的性能。&#xff08;转载请指明出于breaksoftware的csdn博客&#xff09; 删除 头部删除 元素…

一文告诉你,如何使用Python构建一个“谷歌搜索”系统 | 内附代码

来源 | hackernoon编译 | 武明利责编 | Carol出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;在这篇文章中&#xff0c;我将向您展示如何使用Python构建自己的答案查找系统。基本上&#xff0c;这种自动化可以从图片中找到多项选择题的答案。有一件事我们要清楚&…

WatchStor观察:思科携EMC等合作伙伴 圈地数据中心市场

早在今年3月&#xff0c;思科在加利福尼亚州圣何塞市展会中展示了“统一计算系统”(Unified Computing System)之后&#xff0c;我们就明白&#xff0c;数据中心市场将会发生巨大改变&#xff0c;传统的以IBM、惠普、戴尔和Sun为主导的服务器电脑市场&#xff0c;将受到以思科为…

使用BabeLua3.x在cocos2d-x中编辑和调试Lua

BabeLua是一款基于VS2012/2013的Lua集成开发环境&#xff0c;具有Lua语法高亮&#xff0c;语法检查&#xff0c;自动补全&#xff0c;快速搜索&#xff0c;注入宿主程序内对Lua脚本进行调试&#xff0c;设置断点观察变量值&#xff0c;查看堆栈信息等功能。 如何安装 请参考《系…

ASA与PIX的区别

很多年来&#xff0c;Cisco PIX一直都是Cisco确定的防火墙。但是在2005年5月&#xff0c;Cisco推出了一个新的产品——适应性安全产品&#xff08;ASA&#xff0c;Adaptive Security Appliance&#xff09;。不过&#xff0c;PIX还依旧可用。我已听到很多人在多次询问这两个产品…

C++拾趣——STL容器的插入、删除、遍历和查找操作性能对比(ubuntu g++)——遍历和查找

相关环境和说明在《C拾趣——STL容器的插入、删除、遍历和查找操作性能对比&#xff08;ubuntu g&#xff09;——插入》已给出。本文将分析各个容器中遍历和查找的性能。&#xff08;转载请指明出于breaksoftware的csdn博客&#xff09; 遍历 从前往后 元素个数>15000 t…

买不到口罩怎么办?Python爬虫帮你时刻盯着自动下单!| 原力计划

作者 | 菜园子哇编辑 | 唐小引来源 | CSDN 博客马上上班了&#xff0c;回来的路上&#xff0c;上班地铁上都是非常急需口罩的。目前也非常难买到正品、发货快的口罩&#xff0c;许多药店都售完了。并且&#xff0c;淘宝上一些新店口罩库存写着非常多&#xff0c;但不发货&#…

GlusterFS下如何修复裂脑文件?(续一)

关于网上一些修复GlusterFS裂脑文件的说明1、Fixing a GlusterFS split-brainhttps://inuits.eu/blog/fixing-glusterfs-split-brain在该文章中&#xff0c;删除无效副本时提供的方法如下&#xff1a;srv02$ sudo find /export/brick1/sdb1/ -samefile /export/brick1/sdb1/tes…

MySQL数据库环境使用全过程

在使用MySQL之前&#xff0c;需要建立数据库的环境来创建数据表&#xff0c;首先我们需要安装该数据库环境&#xff0c;即MySQL。1、下载MySQLMySQL的官方网站是http://www.mysql.org/&#xff0c;如图2-9所示&#xff1a;图2-9 MySQL官方网站当前稳定版本为5.1&#xff0c;我…

C++拾趣——STL容器的插入、删除、遍历和查找操作性能对比(Windows VirtualStudio)——插入

操作系统是Windows10 64bit&#xff0c;编译器是 Microsoft Virtual Studio Community 10。编译产出是64位测试程序。&#xff08;转载请指明出于breaksoftware的csdn博客&#xff09; 因为加入测量&#xff0c;就会导致误差。我已经尽量将环境影响降低&#xff0c;但是还是难免…

“夸夸机器人”App来了:变身百万粉丝大V,48万人给你的帖子点赞

来源 | mashable译者 | Kolen出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;我在Botnet上的第一条帖子获得了48万个赞。一款全新的社交媒体风格的应用为用户提供了生活在一个奇特网络虚拟世界的机会。在这个世界里&#xff0c;你将拥有数以百万计的粉丝&#xff0c;…

leetcode Reverse Linked List

Reverse a singly linked list 对于这种可以修改值的&#xff0c;把值逆序就可以了。。。。用vector存&#xff0c;然后逆序读。 都忘了指针怎么赋值初始化了。*p&head; 1 /**2 * Definition for singly-linked list.3 * struct ListNode {4 * int val;5 * Lis…

抗击新冠肺炎,如何进行实时动态时序图谱建模与分析?

作者 | 闭雨哲来源 | ThutmoseAI背景介绍新冠肺炎是一种具有最长达24天潜伏期的新型突发性传染疾病&#xff0c;这种特性给疫情防控带来了巨大的挑战&#xff0c;随着感染规模的不断扩增&#xff0c;简单的人为治理已不太奏效&#xff0c;使用“大数据”技术手段来辅助人为治理…

C++拾趣——STL容器的插入、删除、遍历和查找操作性能对比(Windows VirtualStudio)——删除

相关环境和说明在《C拾趣——STL容器的插入、删除、遍历和查找操作性能对比&#xff08;Windows VirtualStudio&#xff09;——插入》已给出。本文将分析从头部、中间和尾部对各个容器进行删除的性能。&#xff08;转载请指明出于breaksoftware的csdn博客&#xff09; 删除 …

关于服务器启动慢的问题

今天去了家医院的机房&#xff0c;走进去一看&#xff0c;TMD的医院就是有钱&#xff0c;全是光纤和千兆网络环境&#xff0c;全全是思科的三层交换机和路由器&#xff0c;HP的服务器。我们需要安装点东西&#xff0c;登录一台服务器&#xff0c;我一看配置&#xff0c;呵呵&am…