2005年04月12日

有个朋友让我谈谈SharePoint2003的文件存储机制,正好这个月一直在做与SharePoint相关的工作,随便说说吧。有对SharePoint很熟悉的朋友也可以对我的理解加以指导和纠正。

SharePoint这个词包含两个东东,一个是Team Service,这是一些服务,提供了方便的站点、文档等东东的管理,以编程接口的方式提供,我们可以直接通过其SDK来调用其服务,现在最新的2003版已经集成进Windows Server 2003了(通过Windows Update就可以安装,或者去MS网站上下载),名字也叫做Windows SharePoint Service 2.0了。

另外一个就是Portal Server,这是一个可以直接建立门户站点的东东,安装上以后,通过其Adminstration Center,就可以直接在IIS的虚拟主机上直接建立站点,并把诸如文档库、列表、论坛等模块加入到站点中。最新的版本是Portal Server 2003,MS中国站点首页上已经有中文版的广告了。

其实上,Portal Server也是调用后面SharePoint Service的接口,只不过把站点的模板都做好了,可以直接拿来用了。Portal Server定义了一种CAML,用来描述站点页面模板。不过偶自己的感觉是是这个东东并不方便,改Portal Server的模板太麻烦了。

SharePoint Service是免费的,Portal Server是要钱的(估计价格不会很低)。

SharePoint里面一个很有特色的东东是WebPart,实质上就是一个CustomControl,特别的是,它可以在Portal Server的站点上,由用户自定义把一个WebPart放在页面上。

SharePoint把所有的东东都存放在Sql Server 2000里面的,文档、图片…只不过通过编程接口可以以更直接的比如SPFolder、SPFile对象把他们当作文件夹、文件来处理(实际上站点服务器上是不会真的给你建立这些文件夹、文件的,都存放在数据库里面)。如果以单服务器模式安装Portal Server,它会自动给你装上一个MSDE。

另外顺便提一下,好像现在在web程序中使用Access的情况是越来越少了,以前ASP时代,很多程序都用Access来保存数据,现在越来越多的是宁愿用MSDE,少量数据则用xml。

2005年01月15日

 用手机上网已经有好长一段时间了,每次在和朋友交流经验时,总会发现很多朋友对CMWAP和CMNET的区别还是不甚了解。对于一些新软件,经常有人会问“CMWAP可以用吗?”,所以笔者撰写了此文,希望本文能为大家解开这个疑惑。

 

  问题1.为什么会有两个接入点?

  在网上查阅大量资料后并经过反复的尝试与探索后,笔者对CMWAP和CMNET两种上网方式作出了一下总结:在国际上,通常只有一种GPRS接入方式,为什么在中国会有CMWAP和CMNET两兄弟呢?(彩信之所以单独配置接入点是因为彩信服务需要连接专用的服务器,在这里不作探讨。)其实,CMWAP 和 CMNET 只是中国移动人为划分的两个GPRS接入方式。前者是为手机WAP上网而设立的,后者则主要是为PC、笔记本电脑、PDA等利用GPRS上网服务。它们在实现方式上并没有任何差别,但因为定位不同,所以和CMNET相比,CMWAP便有了部分限制,资费上也存在差别。

  问题2.什么是WAP?

  WAP只是一种GPRS应用模式,它与GRPS的接入方式是无关的。WAP应用采用的实现方式是“终端+WAP网关+WAP服务器”的模式,不同于一般Internet的“终端+服务器”的工作模式。主要的目的是通过WAP网关完成WAP-WEB的协议转换以达到节省网络流量和兼容现有WEB应用的目的。

  WAP网关从技术的角度讲,只是一个提供代理服务的主机,它不一定由网络运营商提供。但据我所知,中国移动GPRS网络目前只有唯一的一个WAP网关:10.0.0.172,有中国移动提供,用于WAP浏览(HTTP)服务。有一点需要注意,WAP网关和一般意义上的局域网网关是有差别的,标准的WAP网关仅仅实现了HTTP代理的功能,并未完成路由、NAT等局域网网关的功能。这就决定了它在应用上所受到的限制。

  问题3.中国移动对CMWAP的限制?

  为了从应用中区别两者的定位,中国移动对CMWAP作了一定的限制,主要表现在CMWAP接入时只能访问GPRS网络内的IP(10.*.*.*),而无法通过路由访问Internet。(少数地区的移动网络可能不存在这一限制。)我们用CMWAP浏览Internet上的网页就是通过WAP网关协议或它提供的HTTP代理服务实现的。

  说到这里,就让笔者自然而然的联想到公司的网络,相信不少工作的朋友都有类似的体会。公司的网络在网关上不提供路由和NAT,仅仅提供一个可以访问外网的HTTP代理。这样,我们就无法直接使用QQ、MSN等非HTTP协议的应用软件了(好在它们还提供的有HTTP代理的连接方式),CMWAP也正是。

  问题4.CMWAP和CMNET的适用范围

  两种上网连接方式的适用范围才是大家最关心的问题。CMNET拥有完全的Internet访问权,这里就不多说了,主要让我们来看看CMWAP。因为有了上面提到的限制,CMWAP的适用范围就要看WAP网关所提供的支持了。目前,中国移动的WAP网关对外只提供HTTP代理协议(80和8080端口)和WAP网关协议(9201端口)。

  因此,只有满足以下两个条件的应用才能在中国移动的CMWAP接入方式下正常工作:

  1. 应用程序的网络请求基于HTTP协议。

  2. 应用程序支持HTTP代理协议或WAP网关协议。

  问题5.如何辨别一个应用程序的网络请求是否基于HTTP协议?

  这个问题还真不好回答,要完全做到这一点需要通过拦截应用程序的通信数据包进行分析。这里提供几个简单的方法给广大朋友:从表现上看,如果它的网络请求是网址(URL)的形式,那么通常是基于HTTP协议的,如Web浏览器;如果它连接的服务器端口是80,那么它可能是基于HTTP协议的。

  问题6.如何区别一个应用程序支持HTTP代理协议还是WAP网关协议呢?

  首先看它的设置中有没有代理服务器的选项,如果有则表示它支持HTTP代理协议。如果没有,则需要按照以下步骤测试:

  在GPRS接入点设置的高级设置里去掉代理服务器的设置项:Server Address 和 Server Port,如果应用程序可以正常工作,那么它是基于WAP网关协议,如Java程序、S60内置的浏览器。如果在此状态下不能正常工作,而恢复GPRS接入点高级设置中的代理服务器设置后能够正常工作,则应用程序支持HTTP代理协议(代理设置从系统中读取)。如果仍不能正常工作,那么这个应用程序一般来说是不支持HTTP代理协议或WAP网关协议的。

  这里需要特别说明的是JavaQQ,它有Socket和HTTP两种版本。现在网上流传的可用于CMWAP的JavaQQ就是基于HTTP协议的。就拿那个JavaQQ 2004来说,启动画面中就明确的写着“KJava QQ HTTP”。而SIS版的QQ和AgileMessenger(S60的MSN客户端)因为是采用的普通的Socket连接方式,因此无法用于CMWAP。


  最后笔者总结了一下,CMWAP下可以使用的常见软件的工作方式:

  (1) 手机内置的浏览器:WAP网关协议

  (2) Opera 浏览器:HTTP代理协议(有代理设置)

  (3) Java 程序:WAP网关协议

  (4) AvantGo:HTTP代理协议(有代理设置)

  手机上网现在已经被许多手机用户广泛使用,笔者谨希望这篇文章能对用手机上网的用户有所帮助。

2004年12月16日

<!– 时钟clock_035.swf 的035为时钟样式,可自己选择 –>
<EMBED SRC=http://www.butabon.com/Clock/digital_010.swf WIDTH=150 HEIGHT=90 wmode=transparent quality=high loop=true menu=false>

<!– Blog日历表开始 –>
<script language=”javascript”>
var diarydays=”<2004-08-05><2004-08-09><2004-08-12><2004-08-17><2004-08-19><2004-07-14><2004-07-13><2004-07-08><2004-07-05><2004-07-04><2004-07-03><2004-06-27><2004-06-26><2004-06-25>”;
</script>
<meta http-equiv=”Content-Type” content=”text/html; charset=gb2312″>
<style>
.calendarBigBorder { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; text-decoration: none; width: 170; background-color: #FFFFFF; font-size: 9pt;border:1px dotted #999; }
.calendarTd { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; color: #000000; background-color: #eeeeee; height: 18px; width: 11%; text-align: center;}
.calendarMInput { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; text-decoration: none; background-color: #FFFFFF; height: 15px; border: 1px solid #666666; width: 19px; color: #0099FF;}
.calendarYInput { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; color: #0099FF; text-decoration: none; background-color: #FFFFFF; height: 15px; width: 34px; border: 1px solid #666666;}
.calendarMonthTitle { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; font-weight: normal; height: 24px; text-align: center; color: #333333; text-decoration: none; background-color: #eeeeee; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-bottom-style: none; border-top-color: #999999; border-right-color: #999999; border-bottom-color: #999999; border-left-color: #999999;}
.calendarNow { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; font-weight: bold; color: #000000; background-color: #C0C9D3; height: 18px; text-align: center;}
.calendarDaySat { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; color: #333333; text-decoration: none; background-color: #eeeeee; text-align: center; height: 18px; width: 12%;}
.calendarDaySun { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; color: #333333; text-decoration: none; background-color: #eeeeee; text-align: center; height: 18px; width: 12%;}
.calendarLink { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; font-weight: normal; color: #333333; text-decoration: none; background-color: #E7E7F6; text-align: center; height: 18px;}
.categoryTxt { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; line-height: 23px; color: #333333; text-decoration: none;}
.categoryTable { border-right-width: 1px; border-bottom-width: 1px; border-right-style: solid; border-bottom-style: solid; border-left-style: none; border-right-color: #000000; border-bottom-color: #000000; border-top-width: 1px; border-top-style: solid; border-top-color: #71b99c;}
</style>
<SCRIPT LANGUAGE=”JavaScript”>
var months = new Array(“一”, “二”, “三”,”四”, “五”, “六”, “七”, “八”, “九”,”十”, “十一”, “十二”);
var daysInMonth = new Array(31, 28, 31, 30, 31, 30, 31, 31,30, 31, 30, 31);
var days = new Array(“日”,”一”, “二”, “三”,”四”, “五”, “六”);
var classTemp;
var calendarHover=”calendarHover”;
var today=new getToday();
var year=today.year;
var month=today.month;
var newCal;
//得到某月天数
function getDays(month, year)
{ if (1 == month)
     return ((0 == year % 4) && (0 != (year % 100))) ||(0 == year % 400) ? 29 : 28;
  else
     return daysInMonth[month];
}
//得到当天时间信息
function getToday()
{  this.now = new Date();
   this.year = this.now.getFullYear();
   this.month = this.now.getMonth();
   this.day = this.now.getDate();
}
//生成日历
function Calendar()
{  newCal = new Date(year,month,1); //当前月的第一天
   today = new getToday();  
   var day = -1;   //用来判断日历中是否为当天
   var startDay = newCal.getDay(); //当月开始时间
   var endDay=getDays(newCal.getMonth(), newCal.getFullYear());//当月结束时间
   var daily = 0;   //用来生成日历中的天数值
   if ((today.year == newCal.getFullYear()) &&(today.month == newCal.getMonth()))
      day = today.day;
   var caltable = document.all.caltable.tBodies.calendar;  //得到日历表格的集合
   var intDaysInMonth =getDays(newCal.getMonth(), newCal.getFullYear()); //得到当月天数
   //生成日历
   for (var intWeek = 0; intWeek < caltable.rows.length;intWeek++)
     for (var intDay = 0;intDay < caltable.rows[intWeek].cells.length;intDay++)
     {
      var cell = caltable.rows[intWeek].cells[intDay];   //得到单元袼
   //生成字符串用于判断当天是否有日志
      var montemp=(newCal.getMonth()+1)<10?(“0″+(newCal.getMonth()+1)):(newCal.getMonth()+1);        
      if ((intDay == startDay) && (0 == daily)){ daily = 1;}
      var daytemp=daily<10?(“0″+daily):(daily);
      var d=”<”+newCal.getFullYear()+”-”+montemp+”-”+daytemp+”>”;
   //选择样式
      if(day==daily)
      cell.className=”calendarNow”;
      else if(diarydays.indexOf(d)!=-1)
         cell.className=”calendarLink”;
      else if(intDay==6)
      cell.className = “calendarDaySat”;
      else if (intDay==0)
      cell.className =”calendarDaySun”;
      else
      cell.className=”calendarTd”;
   //生成值
      if ((daily > 0) && (daily <= intDaysInMonth)) 
      {  cell.innerText = daily;
         daily++;
      }
      else
        cell.innerText = “”;
    }
  document.all.year.value=year;
  document.all.month.value=month+1;
}

function subMonth()
{
  if ((month-1)<0)
  {
     month=11;
  year=year-1;
  }
  else
  {
    month=month-1;
  }
  Calendar();
}
function addMonth()
{
  if((month+1)>11)
  {
    month=0;
    year=year+1;
  }
  else
  {
    month=month+1;
  }
  Calendar();
}
//得到响应事件
function getDiary()
{
  var mon=(newCal.getMonth()+1)<10?(“0″+(newCal.getMonth()+1)):(newCal.getMonth()+1);
  var day=event.srcElement.innerText<10?(“0″+event.srcElement.innerText):(event.srcElement.innerText);
  var d=”<”+newCal.getFullYear()+”-”+mon+”-”+day+”>”;
  if (“TD” == event.srcElement.tagName)
  if ((“” != event.srcElement.innerText)&&(diarydays.indexOf(d)!=-1))
  {
   diary.location=”/foxmail/archive/”+newCal.getFullYear()+”/”+mon+”/”+day+”.aspx”;
   window.location.href = diary.location;
  }
}

function setDate()
{
  if (document.all.month.value<1||document.all.month.value>12)
  {
    alert(“月的有效范围在1-12之间!”);
 return;
  }
  year=Math.ceil(document.all.year.value);
  month=Math.ceil(document.all.month.value-1);
  Calendar();
}
</SCRIPT>
<table border=”0″ cellpadding=”0″ cellspacing=”1″ class=”calendarBigBorder” id=”caltable” width=”200″>
<thead>
     <tr align=”center” valign=”middle”>
    <td colspan=”7″ class=”calendarMonthTitle”>
   <input name=”year” type=”text” class=”calendarYInput” size=”3″ maxlength=”4″ onkeydown=”if (event.keyCode==13){setDate()}” onkeyup=”this.value=this.value.replace(/[^0-9]/g,”)”  onpaste=”this.value=this.value.replace(/[^0-9]/g,”)”>年
   <input name=”month” type=”text” class=”calendarMInput” size=”1″ maxlength=”2″ onkeydown=”if (event.keyCode==13){setDate()}” onkeyup=”this.value=this.value.replace(/[^0-9]/g,”)”  onpaste=”this.value=this.value.replace(/[^0-9]/g,”)”>月 [<a onClick="addMonth()" href="javascript:;">下月</a>] [<a  onClick="subMonth()" href="javascript:;">上月</a>]</td>
  </tr>
 <tr align=”center” valign=”middle”>
 <SCRIPT LANGUAGE=”JavaScript”> 
 document.write(“<TD class=calendarDaySun id=diary>” + days[0] + “</TD>”);
 for (var intLoop = 1; intLoop < days.length-1;
 intLoop++)
 document.write(“<TD class=calendarTd id=diary>” + days[intLoop] + “</TD>”);
 document.write(“<TD class=calendarDaySat id=diary>” + days[intLoop] + “</TD>”);
 </SCRIPT>
 </TR>
</thead>
  <TBODY border=1 cellspacing=”0″ cellpadding=”0″ ID=”calendar” ALIGN=CENTER ONCLICK=”getDiary()” onmouseup=document.selection.empty() oncontextmenu=”return false” onselectstart=”return false” ondragstart=”return false” onbeforecopy=”return false” oncopy=document.selection.empty() onselect=document.selection.empty()>
    <SCRIPT LANGUAGE=”JavaScript”>
  for (var intWeeks = 0; intWeeks < 6; intWeeks++) {
  document.write(“<TR style=’cursor:hand’>”);
  for (var intDays = 0; intDays < days.length;intDays++)
  document.write(“<TD class=calendarTd onMouseover=’{classTemp=this.className;this.className=calendarHover}’ onMouseOut=’this.className=classTemp’></TD>”);
  document.write(“</TR>”);
  }
 </SCRIPT>
  </tbody>
 </table>
<script  LANGUAGE=”JavaScript”>
Calendar();
</script>
<!– Blog日历表结束 –>

<!– 天气预报 注意这里涉及到编码问题,%B1%B1%BE%A9为城市代码,可用百度查一下,比如输入北京,地址栏中就会出现%B1%B1%BE%字样的内容–>
<iframe width=157 height=240 frameborder=0 scrolling=NO src=’http://appnews.qq.com/cgi-bin/news_qq_search?city=%C9%CF%BA%A3′></iframe>


<!– 显示msn在线状态,注意:必须在msn中设置允许所有人查看你的状态才有效,否则msn图标永远发灰 –>
<br>jagzl@hotmail.com<a href=”http://snind.gotdns.com:8080/message/msn/jagzl@hotmail.com”><img src=”http://snind.gotdns.com:8080/msn/jagzl@hotmail.com
align=”absmiddle” border=”0″ alt=”MSN在线状态指示” onerror=”this.onerror=null;this.src=’http://snind.gotdns.com:8080/image/msnunknown.gif’;”></a>

<!– QQ在线状态显示 –>
<br>QQ:5509398<a href=http://wpa.qq.com/msgrd?V=1&Uin=5509398&Site=donewsblog&Menu=yes target=”_blank”><img border=”0″ SRC=http://wpa.qq.com/pa?p=1:5509398:5 alt=”点击这里给我发消息”></a>