2009-10-5 23:06:21
当你享受的web服务因为黑客攻击无法正常工作时,我们能做的仅仅是等待。等待多久?10分钟、1个小时、6个小时、24个小时、3天还是1个月?如果是没有汽车和飞机的封建社会可能还能忍受3、5个月才能送递一封信的漫长,可这是什么,这是互联网,以光速传递的互联网,你商务中国,让数万域名无法访问,并且等待的时间从9月27日到10月5日仍未结束,这能说明什么呢?至少说明你商务中国不是一个负责的公司,你根本不配在你的商标中注册中国二字。如此状态,只能成为另一个三株口服液。商务中国让你在你的沉闷中消失吧;商务中国,让你随着你沉默的DNS和客服服务放假去吧。
以下摘抄网友评论,以下内容不完全代表本人意志:
回复:商务中国的域名解析服务器被攻击了,网站都打不开了
我们的上百个域名无法正常打开,时好时坏商务中国,你真该好好加强一下技术力量了!
作者:户撒刀王 2009-9-29 20:56 回复此发言
没法跟万网比呀,万网24小时值班,商务中国电话没人接...这就是差距,有机会转到万网去.
现在是不是还是不行啊
我们的域名有的可以打开,有的打不开
非常不稳定
作者:121.28.88.* 2009-10-1 16:12 回复此发言
商务中国的服务的确太差了,电话没人接,也没在线客服,这么多天域名解析不正常,28号公告确说解决了,骗谁啊!目前1号还打不开 ,不知是没水平还是没道德,这样下去快关门了
作者:125.112.25.* 2009-10-1 21:03 回复此发言
晕了,这么多天了还是偶尔打开一次,打电话,没人接,什么骗子公司啊,让我们损失惨重
作者:125.65.167.* 2009-10-1 22:29 回复此发言
建议大公司的网站。不要用商务中的域名解析服务。我给市政府做的网站说是10月1日试运行的。我9月30日访问能正常的。10月1日与市长一起等待网站开张。一片空白。领导不懂这方面。只一句话说我是骗子。我在这个城市没有办法混了。QQ:49554791。建议大家组团索赔。空间用临时地址域名能访问。
作者:58.54.63.* 2009-10-2 09:57 回复此发言
商务中国域名,从28日到今天也没有好.强烈气愤!!
同一网站,有的地方能打开,有的地方打不开.
受其影响,损失严重!
我们保留追究其责任的权利.
同时,我们对商务中国相关防范技术深表失望!太讲不过去了,你们的技术都是割草出身啊??
商务中国在出现这么多天问题后还没解决好,而且没有做好解释工作,没道德没职业操守!!!
作者:sye51 2009-10-2 16:16 回复此发言
妈的这B的什么域名啊还敢有中国2个字 中国人霉都被你倒光!!你们倒好 国庆自己休息去了 我们这么多人的域名都受罪 你知道损失多少钱吗? 这样的垃圾服务器攻击都防不了 明知道被攻击转移服务器不行吗? 买你域名真TM倒了八辈子霉.看我下辈子都不进你这垃圾站了 真想臭骂
作者:218.73.164.* 2009-10-2 20:11 回复此发言
还有这狗B网站连联系他们电话都根本联系不到的 真TM火
作者:218.73.164.* 2009-10-2 20:13 回复此发言
都遇到这情况了,还赶公告放假,放TMB,就没见过这种公司,我公司上千个域名不正常,导致很多上万流量的客户的站都被降权和被K收录了,现在找我们打官司,索赔偿,这样的损失怎么办,
这种公司太差了,大家都走人到万网去。
作者:好玩大家一起来 2009-10-2 20:19 回复此发言
操商务中国的祖宗十八代,我的域名到现在还打不开,都4天了,还不解决,没那技术就别出来混啊,
----------------------------------
致:攻击商务中国的黑客:你们攻击DNS服务器有什么用啊,受损失的都是我们这些无辜的人,有本事把商务中国的网站一起黑了!!!
作者:lmczq163m 2009-10-2 20:43 回复此发言
现在4号了,偶尔有上,真晕啊。
作者:119.134.8.* 2009-10-4 10:33 回复此发言
现在5号了,偶尔破天荒的打得开一次
作者:221.10.18.* 2009-10-5 14:18 回复此发言
阅读全文>>
2009-10-6 2:40:32
为了逃避邮件地址搜索器的搜索,很多站点的邮件地址的显示方式都用了转换方式,比如用图片、替换@、javascript等方式来显示。我比较推崇 javascript这种方式,因为如果真有谁想给你发送邮件的话,可能他更希望的是复制,而不是一个一个字符的输入邮件地址,虽然用其他字符替换也不 错,别人复制了仅需要修改一个字符就Ok,但毕竟没有Javascript的方式好。更进一步讲,别人增加邮件地址搜索器的防替换功能,你即使替换了@字 符,也可能被搜索到。
javascript显示邮件的方式就多种多样了,比如document.write、为HTML元素增加一个子元素并设置 innerHTML(innerText)等等。javascript显示邮件地址的方式能防止被搜索到的根本原因在于用户看到的文本信息是存在于浏览器 的内存当中,而不是实际文件方式存在的,一般的搜寻器都是分析网页源代码来获取Email地址的。
阅读全文>>
2009-10-6 3:19:59
验证码,不用解释,用于区别人和机器的手段。
大多数验证码都采用图片方式,还有有声音和视频(包括Flash)方式的,采用图片是因为目前的图片识别技术还不够成熟,很难把图片上的文字还原成字符文本,这使得给现在的验证码提供了一个基石,倘若哪天图片识别已不是问题,验证码们不得不另谋媒体了。除了上面的几种方式,也有把验证码存储在网页文件或者Cookie中的,这两种方式可能能够瞒过那种专注在discuz、dvbbs、Phpwind等灌水的程序。但若是你的站点真是一个好站,在没有其他防灌水机前提下使用这两种方式存储验证码的话可能要被人罐饱。所以啊,验证码的存储要找个安全的地方放置。一般验证码都是存储在服务器上的,比如Session。
不过现在的网民们越来越抱怨验证码的复杂,复杂得瞅了半天输入的结果还是错误的,更有甚者瞅了半天没看出个字符来,有点像在玩苏轼的横看成岭侧成峰,远近高低各不同。一方面为了防止恶意程序,另一方面为了勉强用户体验,验证的方式也变得五花八门了, 比如做算术题、常识题什么的,真是道高一尺魔高一丈。
不过我对于数字、字母组合的验证码有个建议,就是不要把大写字母O、小写字母o、数字0、大写字母I、数字1加入验证码生成范畴了,这几个字符经过复杂变化实在是难以区分。
阅读全文>>
2009-10-7 0:04:58
上次做了个东西,用了多线程,现总结如下。
使用多线程是为了提高CPU的利用率,即在在相同的时间里面做更多的事情(但前提是系统资源没有完全耗尽),ASP.NET中使用多线程可以加快页面在服务器端的生成速度。一般页面生成过程中花费时间最多的是数据库查询阶段,如果你的页面有10个查询,不使用多线程的话,这10个查询将是串行执行的即依次执行每一个查询。如果使用多线程,将可以使这10个查询几乎同时执行。这显然会提高页面的生成速度。
在网上搜索了些许帖子说在IIS进程中使用多线程是不稳定的,可我经过实践却发现ASP.NET使用多线程也没出啥问题。不过在ASP.NET中使用多线程得注意一些地方,不然确实是不稳定,甚至是行不通的。比如不能在多线程中使用HttpContext下的任何方法和属性,这就包括Cookie、Session、Response、Request、Application等等,当使用这些方法或者属性的时候,IIS进程将会直接崩溃。更要注意的是,由于多线程与页面的加载(Load)是异步执行的,必须让这些创建的线程在Load执行完之前同步,不然可能导致数据没有加载成功。 可能会有人问HttpContext等都被限制了,页面中还能做什么呢?我们完全可以把创建的线程与页面主体隔开,把需要的数据先在页面主体中获取,然后直接传入到创建的线程中就可解决。话不多说,具体如何,请看下文。
假设某个页面中有2个SQL查询,一个是根据Url传递来的参数P确定当前页的内容,另一个查询是显示所有分类。第一个查询语句需要用到Request.QueryString获取P传递来的页码,第二个查询语句则可直接写SQL语句。
假设第一个查询语句如:SELECT * FROM Archives WHERE Page=传递的页码
假设第二个查询语句如:SELECT * FROM Category
我们先创建一个类,用于接受参数P和数据绑定控件ID(此处使用Repeater控件绑定数据),此类能够把SQL语句查询的结果绑定到数据控件(Repeater)中。
复制代码
public classBindData
{
private int currentPage = 1;
private Repeater rpID;
public BindData(Repeater rpID)
{
this.rpID = rpID;
}
public BindData(Repeater rpID,int page)
{
this.rpID = rpID;
this.currentPage = page;
}
public void BindCategory()
{
string strSql=SELECT * FROM Category;
this.BindDataToRepeater(strSql, this.rpID);
}
public void BindArchive()
{
string strSql = string.Format(SELECT * FROM Archives WHERE Page={0},this.currentPage);
this.BindDataToRepeater(strSql, this.rpID);
}
private void BindDataToRepeater(string strSql, Repeater rp)
{
if (rp == null) return;
SqlConnection conn = new SqlConnection(data source=数据服务器地址;User ID=用户名;pwd=密码;Initial Catalog=数据库名);
SqlCommand cmd = new SqlCommand(strSql, conn);
SqlDataReader dtr;
try
{
conn.Open();
dtr = cmd.ExecuteReader();
controlID.DataSource = rp;
controlID.DataBind();
if (!dtr.IsClosed)
dtr.Close();
}
catch { }
finally
{
cmd.Dispose();
if (conn.State = ConnectionState.Open)
conn.Close();
}
}
}
上面创建的BindData类中有2个构造函数,分别用于绑定分类、绑定Arhive的不同形式。如果使用其他数据绑定控件则可进行相应修改;
创建了1个私有方法BindDataToRepeater用于把对应的SQL语句查询的结果绑定到对应的Repeater控件上。同时在此方法中使用了SqlDataReader,以提高绑定数据的速度。如果你使用了数据工厂可修改BindDataToRepeater中的具体实现过程;
2个共有方法BindCategory和BindArchive分别用于创建不同SQL语句、设置Repater的ID;
同时需要引入System.Web.UI、System.Web.UI.HtmlControls、System.Data.SqlClient3个必要的命名空间。
值得注意的是在BindDataToRepeater方法中使用了try..catch语句,但并没有在catch块中做任何事情,为什么我们用try.catch却不在catch块中做点什么事情呢,不是多此一举吗?使用try..catch是为了防止在执行BindDataToRepeater时抛出异常,若此处出现异常且此方法是在多线程中执行的,将会导致IIS进程崩溃,进而影响其他页面的正常执行,故而用try...catch防止BindDataToRepeater抛出错误。
我们之所以为数据绑定创建一个类,是为了提高内存利用率,当数据加载(Load)完毕的时候,为这个类创建的实例就会销毁。我们也可以通过在页面中创建几个全局变量来实现。但我还是建议以类的形式传递数据而不是使用全局变量。下面,我们开始在页面的Load中创建线程了。首先你需要在页面中引入System.Threading命名空间。
复制代码
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
int Page = 1;
if(Request.QueryString[p]!=null)
Page = Convert.ToInt32(Request.QueryString[p]);
BindData LoadArchives = new BindData(rpArhive,Page);
Thread thArhives=new Thread(new ThreadStart(LoadArchives.BindArchive));
thArhives.Start();
BindData LoadCategory=new BindData(rpCategory);
Thread thCategory = new Thread(new ThreadStart(LoadCategory.BindCategory));
thCategory.Start();
//进行页面的其他非数据绑定操作
thArhives.Join();
thCategory.Join();
}
}
上面的代码显示在!IsPostBack状态下绑定数据。利用Request.QueryString获取了当前页码,并创建了BindData的2个实例LoadArchives、LoadCategory,通过 Thread thArhives=new Thread(new ThreadStart(LoadArchives.BindArchive))为绑定Arhice创建线程,通过Thread thCategory = new Thread(new ThreadStart(LoadCategory.BindCategory))为绑定分类创建线程,同时调用Thread的Start方法使2个线程进入执行状态。最后,在Load的最下面用Thread的Join方法使创建的2个线程与页面加载同步。
值得注意的是,Join方法是必须的,如果不使用,可能导致创建的线程还未把数据完全绑定到Repeater上,Load就已经执行完毕,若如此页面上将没有任何数据。同时调用Start的代码行应尽量早,调用Join的代码行都应尽量迟尽量放在Page_Load代码段的末尾,这样才能达到多线程的目的,若你每调用一个Start马上调用Join,其实质和没有使用多线程的效果是一样的。Join在MSND上的解释是:在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻塞调用线程,直到某个线程终止为止。
只要设置好ASPX页面Repeater的绑定项,数据就可成功加载了。上面仅仅展示了2个SQL语句的查询,如果你有10个或者更多的SQL查询,在Page_Load中创建10个线程,让他们异步执行,最后用Join同步到Load,是一个提高性能的不错方法。
本文由Goberl理解实践,但个人能力有限,若有错误,望请指教!
阅读全文>>
2009-10-8 1:47:22
在B/S结构中要实现定时器(或者说是一个事务)实在不是一件好办的事。可当你在网上搜索ASP.NET定时器的时候,你会发现搜索结果是如此的多,可这大多数结果中的代码健壮性都是那样的脆弱没有考虑诸如IIS进程的自然消亡、IIS进程的故障崩溃、重启服务器等等因素。这些不可捕捉的错误会让你的定时器失去定时的功能。可能会有人问,为什么要用Web程序做计时器呢?自己添加一个Windows服务或者在数据库中添加一个作业不就解决了么?可事实上,又有多少人对自己购买的虚拟主机具有如此权限呢?如果你用的是自己的服务器或者更高权限的服务器,那此文对你的确是多余了。
我曾经为ASP.NET中的Application_End感到窃喜,以为有了它,以上提及的自然消亡、故障崩溃都可迎刃而解了,可经过自己的实践发现那个Application_End真的是很无助你在该代码段真的是nothing to do。国内搜索到的所谓ASP.NET定时器几乎都是采用System.Thread进程监控实现的,要让Thread在IIS进程中保持长期(比如1年365天时时刻刻)的稳定性实在是不敢打包票。
最后我在CodeProject上找到一篇文章《Simulate a Windows Service using ASP.NET to run scheduled jobs》(在ASP.NET中模拟Widnows服务执行计划任务)。在这篇文章中,他利用缓存的过期来实现定时器功能。在ASP.NET中,当你添加缓存的时候,会有一个缓存回调函数让你同时加入,表示当缓存过期被系统清除的时候,你可以在这个回调函数中做一些事情。缓存回调函数正是实现ASP.NET定时器的重要基石。假设我们在00:00:00时刻加入一个缓存对象,缓存的过期时间我们设置为00:02:00,当到达00:02:00或者更提前的时候,缓存将被系统回收,当系统通知缓存被回收的时候我们再次添加一个缓存,如此循环往复(缓存被添加->过期->再次添加->过期)从而模拟出了钟表秒针。当每一次缓存过期的时候我们都检查是否有需要执行的事务,有则执行,然后再次添加一个缓存,从而模拟出了定时器。
但是要想添加缓存,必须有用户请求Web服务器才能使用Cache。所以,在缓存过期的时候,除了检查是否有事务需要执行外,还要用WebClient(或者其他方法)请求我们的Web页面,在页面被请求的时候添加缓存。
上面的思路已经基本模拟出了定时器的功能,但对于服务器重启、IIS故障仍然没有解决。《Simulate a Windows Service using ASP.NET to run scheduled jobs》中提到,可以把Google Robots抓取你网页的频率设置大一点,当出现上述情况时,以尽快的速度产生Web请求。只要有人(或者机器人)在访问你的Web程序,缓存定时器(我们把它称为缓存时钟吧)就可以正常工作,而他的工作是由系统自行维护的,而不是Thread进程维护,所以稳定性会有很大的提高。经过我的实践,只要服务器没有重启、IIS进程没有崩溃,上述中采用在缓冲过期时请求Web页面(WebClient)的行为是不会让IIS进程自然消亡的(缓存过期时间长短、服务器配置也会影响)。(下划线文字的描述与事实不符,观测的结果可能受到网络蜘蛛的影响)具体如何实现,请看下文。
复制代码
using System;
using System.Data;
using System.Net;
using System.Configuration;
using System.Web;
using System.Text;
using System.Web.Caching;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public classCacheTimer
{
const string logPath = @d:\cacheLogs\cacheLog.txt;
const string cacheKeyName = myCacheTimer;//缓存的名字
const string rawUrl = http://localhost/CacheTimer/CacheTimmer.aspx;//缓存过期时请求的页面地址
public void RegistCacheTimmer()
{
if (HttpContext.Current.Cache[cacheKeyName] != null) return;
try
{
HttpContext.Current.Cache.Add(cacheKeyName, '1', null,
DateTime.Now.AddSeconds(12), Cache.NoSlidingExpiration,
CacheItemPriority.High,
new CacheItemRemovedCallback(CacheItemOnRemoved));
WriteCacheLog(缓存时钟注册成功);
}
catch (Exception e)
{
WriteCacheLog(缓存时钟注册失败: + e.Message);
}
}
protected void CacheItemOnRemoved(string key, object value, CacheItemRemovedReason reason)
{
if (key == cacheKeyName)
{
ExeJob();
RequestWebPage();
}
}
protected void ExeJob()
{
WriteCacheLog(被执行了);
//如果日期的天数能被7整除、下午13点到13点15分的时候,则执行
if (DateTime.Now.Day % 7 == 0 DateTime.Now.Hour == 13 DateTime.Now.Minute <= 15)
{
//执行数据操作或者其他任务
}
}
protected void RequestWebPage()
{
WebClient wc = new WebClient();
wc.DownloadData(rawUrl);
}
public static void WriteCacheLog(string logInfor)
{
try
{
System.IO.StreamWriter sw = new System.IO.StreamWriter(logPath, true, Encoding.GetEncoding(GB2312));
sw.WriteLine(DateTime.Now.ToString() + + logInfor);
sw.Close();
sw.Dispose();
}
catch
{
//调试的时候注意是否对该文件有写权限
}
}
}
添加缓存:RegistCacheTimmer
请求页面:RequestWebPage
执行任务:ExeJob
缓存过期时候执行请求页、执行任务:CacheItemOnRemoved
写日志的方法:WriteCacheLog
然后在Global.asax文件中添加下列代码段:
复制代码
void Application_BeginRequest(Object sender, EventArgs e)
{
CacheTimer registTimer = new CacheTimer();
registTimer.RegistCacheTimmer();
}
但是如果我们的任务在没有执行完毕,IIS进程崩溃或者服务器重启了,怎么办?我的建议是把任务写人文件(包括数据库),检查的时候直接检查任务文件就可以保证重启IIS进程,任务不丢失了。
感谢《Simulate a Windows Service using ASP.NET to run scheduled jobs》的作者提供此定时器的解决方法。
Goberl缓存时钟源码下载
阅读全文>>
2009-10-27 13:49:08
上周三到周末把博客改版了,但只修改了后台程序,页面皮肤没有修改。
采用了三层架构;
增加了页面的关键词描述;
部分地方使用多线程;
丢弃以前的web服务,采用jQuery调用Ashx实现ajax;
验证码字符增加随机旋转;
优化了评论、友情链接管理模块;
修复C#高亮代码模块的Bug;
修改RSS仅显示最近发表的12篇新闻;
tag排序的文章页添加分页功能;
全局排序分页、分类排序分页、tag排序分页每页显示文章数和右侧菜单中各个模块调用数均采用了统一配置文件;
可手动设置分类列表的排序情况。
优化了分页查询语句
这次改版最满意的是使用了三层架构,使用它非常有利于以后的升级。这几天在观察运行情况
阅读全文>>