MS的开源项目站 CodePlex
MS的开源项目站
//—————————————————-
第1讲
//—————————————————-
Remoting 使用的技术
XML
SOAP
SerializableAttribute() 或实现ISerializable
//==Bin
FileStream fs = new FileStream("my.bin" , FileMode.Creat);
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs , myObj);
fs.Close();
//==Soap
FileStream fs = new FileStream("my.xml" , FileMode.Creat);
SoapFormatter formatter = new SoapFormatter();
formatter.Serialize(fs , myObj);
fs.Close();
//==XML
FileStream fs = new FileStream("my.xml" , FileMode.Creat);
System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(MyType));
xmlSer.Serialize(fs , myObj);
fs.Close();
远程对象:
对象运行在远程(MarshalByRefObject)
传递对象副本(Serialize)
对象激活
服务器激活SAO(WellKnown)
Singleton
SingleCall
客户端激活
可保存会话状态
Channels
用于收发消息
TCP or Http, 也可自定义
开发remoting的步骤
创建远程对象
public class HelloServer: MarshalByRefObject
{
public
}
创建host程序, 或host在IIS中
注册通道(内置: TCP , HTTP)
注册服务器激活的远程对象, URL
运行宿主对象
建立客户端程序
注册通道(内置: TCP , HTTP)
根据URL得到对象代理
通过代理调用远程对象.
//===Sample : SampleRemoting
public class Client
{
public static void Main(string[] args)
{
//使用TCP通道得到远程对象
TcpChannel chan1 = new TcpChannel();
ChannelServices.RegisterChannel(chan1);
HelloServer obj1 = (HelloServer)Activator.GetObject(typeof(RemotingSamples.HelloServer),"tcp://localhost:8085/SayHello");
if (obj1 == null)
{
System.Console.WriteLine("Could not locate TCP server");
}
//使用HTTP通道得到远程对象
HttpChannel chan2 = new HttpChannel();
ChannelServices.RegisterChannel(chan2);
HelloServer obj2 = (HelloServer)Activator.GetObject(typeof(RemotingSamples.HelloServer), "http://localhost:8086/SayHello");
if (obj2 == null)
{
System.Console.WriteLine(
"Could not locate HTTP server");
}
Console.WriteLine( "Client1 TCP HelloMethod {0}", obj1.HelloMethod("Caveman1"));
Console.WriteLine("Client2 HTTP HelloMethod {0}", obj2.HelloMethod("Caveman2"));
Console.ReadLine();
}
/*
<configuration>
<system.runtime.remoting>
<application>
<client>
<wellknown type="HelloServer, General" url="http://localhost:8086/SayHello" />
</client>
<channels>
<channel ref="http" port="0"></channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>
RemotingConfiguration.Configure(@"C:\Documents and Settings\RenMin\桌面\Remoting\Demo\02-SimpleRemoting\Client\client.exe.config");
HelloServer obj2 = new HelloServer();
*/
}
public class Server
{
public static int Main(string [] args)
{
TcpChannel chan1 = new TcpChannel(8085);
HttpChannel chan2 = new HttpChannel(8086);
//注册通道, server会开始监听该通道
ChannelServices.RegisterChannel(chan1);
ChannelServices.RegisterChannel(chan2);
RemotingConfiguration.RegisterWellKnownServiceType( typeof(HelloServer),
"SayHello" , //URL
WellKnownObjectMode.Singleton //对象类型
);
System.Console.WriteLine("Press Enter key to exit");
System.Console.ReadLine();
return 0;
}
}
//==Remote object
public class HelloServer : MarshalByRefObject
{
public HelloServer()
{
Console.WriteLine("HelloServer activated");
}
public String HelloMethod(String name)
{
Console.WriteLine( "Server Hello.HelloMethod : {0}", name);
return "Hi there " + name;
}
}
}
可传递的类型:
简单类型
可序列化的类型
自定义的类型[serializable]
在Client端直接使用User class
Singleton VS SingleCall
都是服务器激活(WellKnown)
Singleton :
在服务器端只实例化一次
每次调用都是同一实例.
可以维持状态
SingleCall
每次调用都实例化新的实例
Serialization vs MarshalByRefObject
Serialization
副本,不论Singleton还是SingleCall
MarshalByRefObject
通过proxy
Singleton记录更改, SingleCall无状态
判断一个obj是否是一个Proxy
RemotingServices.IsTransparentProxy()
//—————————————————-
第2讲
//—————————————————-
SAO 配置文件 wellknown
<configuration>
<system.runtime.remoting>
<application>
<service>
<wellknown mode="Singleton" objectUri="SayHello" type="RemotingSamples.HelloServer, General" />
</service>
<channels>
<channel port="8086" ref="http"/>
</channels>
</application>
</system.runtime.remoting>
</configuration>
<service>说明是server端
ref实际上是引用machine.config
%WINDIR%\Microsoft.NET\Framework\[version]\CONFIG
<channels>
<channel id="http" type=" "…/>
</channels>
客户端配置文件
<configuration>
<system.runtime.remoting>
<application>
<client>
<wellknown url="http://localhost:8086/SayHello" type="RemotingSamples.HelloServer, General" />
</client >
<channels>
<channel port="0" ref="http"/>
</channels>
</application>
</system.runtime.remoting>
</configuration>
<channel port="0" />client
不需要监听
–代码——————————————————-
Server.cs
public class Server
{
public static int Main(string [] args)
{
RemotingConfiguration.Configure(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
//or RemotingConfiguration.Configure("Server.exe.config");
System.Console.WriteLine("Press Enter key to exit");
System.Console.ReadLine();
return 0;
}
}
Client.cs
public class Client
{
public static void Main(string[] args)
{
//使用HTTP通道得到远程对象
RemotingConfiguration.Configure(@"client.exe.config");
HelloServer obj2 = new HelloServer();
if (obj2 == null)
{
System.Console.WriteLine("Could not locate HTTP server");
}
Console.WriteLine( "Client2 HTTP HelloMethod {0}", obj2.HelloMethod("Caveman2"));
Console.ReadLine();
}
}
基于租约的对象生存期
可参考
使用.NET Remoting开发分布式应用——基于租约的生存期
http://terrylee.cnblogs.com/archive/2005/11/28/285809.html
微软的DCOM技术使用了Ping机制,在这种机制下,客户程序有规律的对服务程序发出Ping请求,
以通知服务程序自己仍旧活着,并通知服务程序自己需要使用哪个对象。
.NET Remoting使用的是基于租约的生存期机制,在租约期内,对象一直存活着,直到租借时间
结束,.NET Remoting使用Leasing程序完成了这项工作。
隐式续约
每次调用远程对象上的方法的时候自动进行。
显示的续约
ILease.Renew()
发起租约
ISponsor接口
ILease.Register()
租约的配置
租约配置 默认值(秒)
LeaseManagerPollTime 300
SponsorshipTimeout 120
RenewOnCallTime 120
InitialLeaseTime (轮讯时间) 10
//–如何得到当前的租约
HelloServer obj = (HelloServer)Activator.GetObject(typeof(RemotingSamples.HelloServer), "http://localhost:8086/SayHello");
ILease lease = (ILease)obj.GetLifetimeService();
if (lease != null)
{
Console.WriteLine("Lease Configuration:");
Console.WriteLine("InitialLeaseTime: " +
lease.InitialLeaseTime);
Console.WriteLine("RenewOnCallTime: " +
lease.RenewOnCallTime);
Console.WriteLine("SponsorshipTimeout: " +
lease.SponsorshipTimeout);
Console.WriteLine(lease.CurrentLeaseTime);
}
//–通过代码改变租约, 见 Helloserver.cs
// Overrides the lease settings for this object.
public override Object InitializeLifetimeService()
{
ILease lease = (ILease)base.InitializeLifetimeService();
// Normally, the initial lease time would be much longer.
// It is shortened here for demonstration purposes.
if (lease.CurrentState == LeaseState.Initial)
{
lease.InitialLeaseTime = TimeSpan.FromSeconds(3);
lease.SponsorshipTimeout = TimeSpan.FromSeconds(10);
lease.RenewOnCallTime = TimeSpan.FromSeconds(2);
}
return lease;
}
//–通过配置改变租约, 见 server的web.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
….
<!–leaseManagerPollTime="7S"–>
<lifetime leaseTime="7M" sponsorshipTimeout="7M" renewOnCallTime="7M"/>
</application>
</system.runtime.remoting>
</configuration>
CAO客户端激活 activated
客户端激活的server端config文件
<application>
<service>
<activated type="ClientActivatedType, General"/>
</service>
</application>
client 端config文件
<application>
<client url="http://localhost:8080">
<activated type="ClientActivatedType, General"/>
</client>
</application>
优点客户端可以保存客户状态
例子为 04-CAOsDemo
客户端发起租约
例子为 05-SponserDemo
客户端发起租约的代码
public class MyClientSponsor : MarshalByRefObject, ISponsor
{
private DateTime lastRenewal;
public MyClientSponsor()
{
lastRenewal = DateTime.Now;
}
public TimeSpan Renewal(ILease lease)
{
Console.WriteLine("I’ve been asked to renew the lease.");
Console.WriteLine("Time since last renewal:" + (DateTime.Now - lastRenewal).ToString());
lastRenewal = DateTime.Now;
return TimeSpan.FromSeconds(20);
}
}
public class Client
{
public static void Main(string[] Args)
{
// Loads the configuration file.
RemotingConfiguration.Configure("client.exe.config");
ClientActivatedType CAObject = new ClientActivatedType();
ILease serverLease = (ILease)RemotingServices.GetLifetimeService(CAObject);
MyClientSponsor sponsor = new MyClientSponsor();
// Note: If you do not pass an initial time, the first request will
// be taken from the LeaseTime settings specified in the
// server.exe.config file.
serverLease.Register(sponsor);
……
}
}
//—————————————————-
第3讲
//—————————————————-
程序发布的模式: console, winform, winService, IIS
需要看源代码
//—————————————————-
第4讲
//—————————————————-
聊天程序
//——————————–
原则
//——————————–
1.设置目标
2.测量
3.了解平台特性
//——————————–
方法论
//——————————–
性能周期: 收集性能数据->分析数据找到问题->solution-> 实现 ->测试->收集性能数据
高质量的代码: 可移植性,可读性,可维护性,可靠性
收集数据:计时器 , 工具: Intel Vtune(收集数据)
负载: 可测量,可再生,静态,有代表性
识别问题: 瓶颈,热点
途径:算法,数据结构, 代码调节, 系统软件, 硬件
//——————————–
.Net 程序优化
//——————————–
StringBuilder
GC的特点:使用弱引用
Ngen
值类型
using 对应的IL代码
//——————————–
工具
//——————————–
Intel Vtune
应用平台: .net(可测到方法一级),c++(可测到代码级)
Performance:
CLR profiler
Dev partner (Compuware)
期望能看到一个性能分析的实例,但结果很失望,咬牙挺到了最后.
1. myStr.Length == 0
2. myString == String.Empty
3. myString==""
4. String.IsNullOrEmpty (2.0)
在1.0时,FxCop推荐使用方法1,但为了防止null refrence,我们得先判一下null.
2.0有了新的静态方法IsNullOrEmpty(),那个最好呢?
使用Reflector打开.net 2,050727 下的mscorlib.dll
1 的代码为
[MethodImpl(MethodImplOptions.InternalCall)]
public extern int get_Length();
2和3 要使用了运算符==,而string的==的代码为
public static bool operator ==(string a, string b)
{
return string.Equals(a, b);
}
string.Equals的代码为:
public static bool Equals(string a, string b)
{
if (a == b)
{
return true;
}
if ((a != null) && (b != null))
{
return string.EqualsHelper(a, b);
}
return false;
}
看到这,你恐怕不会使用这种方法了吧.更有甚者myString==""还会先new一个空串出来.更浪费资源.
4 的代码为:
public static bool IsNullOrEmpty(string value)
{
if (value != null)
{
return (value.Length == 0);
}
return true;
}
正是我们期待已久的答案.
比较string是否相等可以使用静态方法String.Equals(), 也可以调用字符串的实例方法, 用reflector察看mscorlib.dll
–Instance Equals method implementation:
<.net 2.0.50727>
public bool Equals(string value)
{
if ((value == null) && (this != null))
{
return false;
}
return string.EqualsHelper(this, value);
}
<.net 1.1>
[MethodImpl(MethodImplOptions.InternalCall)]
public extern bool Equals(string value);
An internal call is a call to a method implemented within the common language runtime itself.
–Static Equals method implementation:
<.net 2.0.50727>
public static bool Equals(string a, string b)
{
if (a == b)
{
return true;
}
if ((a != null) && (b != null))
{
return string.EqualsHelper(a, b);
}
return false;
}
<.net 1.1>
public static bool Equals(string a, string b)
{
if (a == b)
{
return true;
}
if ((a != null) && (b != null))
{
return a.Equals(b);
}
return false;
}
[*]读EqualsHelper的代码,可以看看MS是怎么比字符串的.
可以看到,静态方法会先比较refrence,如果事先知道字符串相等的可能性较大,使用静态方法会快那么一点点.
进入 Manage->file->修改css,
添加以下部分
#categories ul li
{
margin-left: 6px;
list-style-type: none;
list-style-image: url(http://recordsome.blogsome.com/images/bullet.gif);
}
后来觉得这样不是很好,正解应该是修改css中的Content & menu一节,
将
#menu ul ul {
margin-left: 0;
list-style: disc;
list-style-position: inside;
padding-left: 0.5em;
text-indent: 0;
color: black;
}
改为
#menu ul ul {
margin-left: 0;
list-style-position: inside;
padding-left: 1em;
text-indent: 0;
list-style-type: none;
list-style-image: url(http://recordsome.blogsome.com/images/bullet.gif);
color: black;
}
Cool!目标实现了,但是由于加了icon和padding,右边菜单区域的空间有点太窄了,于是又修改了
#menu {
width: 16em;
增加width的值.
咏蛙
独坐池塘如虎踞,绿荫树下养精神。春来我不先开口,哪个虫儿敢作声。
—1909年,16岁的毛泽东(1893-1976)来到离家50里外的湘乡县(湘军曾国藩属下有2000多个被封为二品以上的军官住在当地) 东山书院读书,做此诗。
题菊花
飒飒西风满院栽,蕊寒香冷蝶难来。他年我若为青帝,报与桃花一处开。
—- (唐)黄巢
不第后赋菊
待到秋来九月八,我花开后百花杀。冲天香阵透长安,满城尽带黄金甲。
—- (唐)黄巢
西江月
自幼曾攻经史,长成亦有权谋。 恰如猛虎卧荒丘,潜伏爪牙忍受。 不幸刺文双颊,那 堪配在江州。 他年若得报冤仇,血染浔阳江口!
心在山东身在吴,飘蓬江海谩嗟吁。 他时若遂凌云志,敢笑黄巢不丈夫!
—- 水浒传 宋江
出自
http://www.cnblogs.com/jjstar/archive/2004/07/02/20354.aspx
我一直有一个误区:只要从System.ServiceProcess.ServiceBase继承一个类并编译好就可以用.net提供的命令行程序InstallUtil.exe安装了。但实际上如果仅仅做了这样的一个类是无法用InstallUtil.exe安装的,在安装时会报错:
这是因为installUtil.exe会用反射的方法去查找所有把RunInstallerAttribute设置为true的System.Configuration.Install.Installer类型,并执行上面的Install方法,当找不到的时候,安装就失败了。
所以我们必须要写一个从Installer类继承的类来满足installUtil.exe的要求。
Get free blog up and running in minutes with Blogsome
Theme designed by Hadley Wickham