RSS 2.0 Feed
2006-11 Entries
摘要:在Thread pooling for web connections中我曾经提到Shared Source CLI,这次再借用另一个场合宣传一下这个"Open Source .NET Framework"吧。 Topic还是web connection pooling:可以很自然地想到我们可以设计这么一个class: class WebConnector {     WebRequest CreateRequest(string targetUrl)     {         return WebRequest.Create(targetUrl);     }     ... } 这个class现在什么都没有做,因为我们的希望是.NET提供的WebRequest可以提供一定的pooling mechanism,如果真是那样,那生活真是很美好,我们什么都不要做就可以下班了。而其实这也不是什么太wild的dream,毕竟是.NET,连个pooling都不提供,也不要混了。 在深入研究一下WebRequest class之前,我们还需要考虑一个问题:web application很常见的会用到其他的web service,也就是用SOAP像其他web service请求服务。在Visual Studio中如何生成web service的proxy class等等我就不用重复重复了吧(wsdl.exe等等的)?关键在于:这个由wsdl自动生成proxy class用的是什么connection mechanism呢?虽然基本可以想到应该也是somewhere, somehow用的WebRequest,但还是让我们double check一下。找任意一份wsdl生成的proxy class的代码看看: public partial class WSProxcyClass : System.Web.Services.Protocols.SoapHttpClientProtocol 嗯,看来基本功能都在SoapHttpClientProtocol这个类里面。 再研究一下MSDN里SoapHttpClientProtocol的API,aha,有这么一个member function: protected override WebRequest GetWebRequest(Uri uri) 看来所有SoapHttpClientProtocol里面用到的WebRequest都是通过这个函数来取得的。注意一下前缀的override关键字,很好很好,这说明如果我们对WebRequest现有的pooling mechanism不满意的话(或者WebRequest根本没有提供pooling机制),我们可以从SoapHttpClientProtocol派生一个类,然后改写掉GetWebRequest来实现我们满意的pooling机制。其他的接口都还是用SoapHttpClientProtocol,而WSProxyClass只要继承新的派生类就可以了。   嗯,很好,至少我们有了backup plan,虽然麻烦了一点点,但也算不错,感谢SoapHttpClientProtocol良好的界面。 现在该进一步了,我们来研究一下WebRequest到底有没有提供pooling吧。 (题外话:可以看到.NET源代码的朋友可以研究一下SoapHttpClientProtocol的实现,这里是一个class hierarchy: WebClientProtocol -> HttpWebClientProtocol     -> SoapHttpClientProtocol : 你会发现,GetWebRequest其实一直延伸到最基类的WebClientProtocol里,有不少messy stuff to deal with,所以真的要改写GetWebRequest并非那么容易。不过,anyway, that's a side note to this article, we are heading for better stuff, baby. ) 这下该用到,搜一下webrequest.cs,嗯嗯,time to read the source code: private static WebRequest Create(Uri requestUri, bool useUriBase) {     string LookupUri;    WebRequestPrefixElement Current = null;    bool Found = false;     if (!useUriBase) {        LookupUri = requestUri.AbsoluteUri;    }    else {    ......[阅读全文]

posted @ | Feedback (2) |

摘要:   很不好意思这么长时间都没有文章了,实在是因为觉得最近接触的很多内容不会有很多人感兴趣,举个例子: mutual SSL authentication with ASP.NET,会有人感兴趣么? 现在写的内容也觉得是marginally appealing,不管了,好歹也写一点。 [Main Reference: http://msdn.microsoft.com/msdnmag/issues/04/12/NETMatters/] 那么这次要说的是在client app中使用HttpWebRequest向server发送服务请求。在.NET 1.x中,如果你并发的HttpWebRequest数量太多的话,你会发现.NET开始抛这样一个exception: There were not enough free threads in the ThreadPool object to complete the operation. 这是什么原因呢? 答案总是在源代码里找。如果你看一下Shared Source CLI里的实现(顺便说一句,很推荐大家去下载一封SSCLI,.NET不是开源的,但SSCLI中的很多实现都忠实地体现了.NET中很多设计的概念和方法),会发现,其实在1.x的.NET framework中,HttpWebRequest其实是Asynchronous的: public override WebResponse GetResponse() {  ....  IAsyncResult asyncResult = BeginGetResponse(null, null);  ....  return EndGetResponse(asyncResult);}   而BeginGetResponse其实是往Thread pool里queue一个work item (用过thread pool的朋友应该很熟悉QueueUserWorkItem这个API)。而这为什么会引起异常呢? 死锁 (deadlock)。 我们假设Thread Pool里只有一个thread,当你第一次调用GetResponse的时候,用掉了Thread pool里唯一的那个thread,GetResponse调用BeginGetResponse queue了一个work item来发送请求,然后再调用EndGetResponse来等待结果返回。不过很不幸,BeginGetResponse永远被执行了,因为唯一的thread已经被GetResponse用掉,而它(EndGetResponse))正在等待BeginGetResponse的返回,deadlock。 那么在现实情况中,thread pool显然不可能只有一个thread。然而,这种情况还是会发生的,比如thread pool有10个thread,当你连续queue 10个work item进去的时候,一样发生死锁。 在1.x中,.NET的权宜之计就是抛异常。在BeginGetResponse的最后,就在queue user work item之前,程序会检查System.Net.Connection.IsThreadPoolLow,如果是true,就跑出InvalidOpeartionException异常。 但如果你看一下上面SSCLI里这部分的实现,你会发现GetResponse里根本没有用到BeginGetResponse/EndGetResponse (呵呵,其实当时我也是一开始就开始看.NET的source code,结果发现根本没有什么BeginGetResponse/EndGetResponse,于是怀疑原文作者是不是在乱扯,后来看到文章的后面才明白),因为在.NET 2.0中,GetResponse已经是真正的使用synchronous call了,于是死锁的问题也不存在了。 那么在1.x的.NET中我们怎么人为干预以防止死锁的发生呢。 最显然的答案自然是使用semaphore(关于semaphore的概念就不讲了吧,大学operating system课程的这个是必修内容)。 但更可怜的是,.NET 1.x居然连semaphore也没有...... (汗,我看到这里才意识到很久以前读Jeff Prosise的《Programming Microsoft .NET Core Reference》的时候居然没有发现Multithreading一章里确实没有提到semaphore一个字)。 那么只能自己wrap一下win32的API了:  public sealed class Semaphore : WaitHandle { public Semaphore() : this(1, 1) {} public Semaphore(int initialCount, int maximumCount) ......[阅读全文]

posted @ | Feedback (7) |

摘要:下载了一个网页,存在本地硬盘上,文件名为:How to send a client certificate by using the HttpWebRequest and HttpWebResponse classes in Microsoft Visual C# _NET.mht 后来想打开看一下,IE7却出现这样的错误: 找了一下原因,原来是“C#”中的“#”造成了问题。应该是IE7在处理mht文件的时候把这个#和html中的anchor混起来了。 在IE6也测试了一下,似乎对这个问题免疫。 Hmm, maybe I should submit a bug to the IE team. Update: This problem is fixed in Vista RTM. It's a problem on XP or earlier version of Vista (such as Beta 2). There may be a fix for this issue on XP platform in the future, but I am not sure....[阅读全文]

posted @ | Feedback (10) |

摘要:Building Secure ASP.NET Application PDF格式,contains pretty much very thing you need to know about securing your ASP.NET web app.   I will also recommend actually reading the web-based version since it may be more up-to-date: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/secnetlpMSDN.asp...[阅读全文]

posted @ | Feedback (3) |