SlideShare una empresa de Scribd logo
1 de 23
WAP(wml)开发 faq --摘自 csdn

1.         开   发    WAP     软   件    需     要    哪      些   工    具    ?

  为了开发 WAP 应用程序,需要一个 WAP 网关(注意:这里的网关可能是指支持 WML 的服务器。可以通
过配置 WWW 服务器达到这个目的)和 WAP 工具包。工具包应当包括模拟器和能让开发者浏览 WML 网页。WML
页面的开发和 HTML 页面的开发一样,可以使用 Notepad 或者其他文本编辑器来进行编辑。

2. 有哪些公司现在提供这样的开发环境?

Nokia、Ericsson、UpPhone 和 Motorola 都提供免费的 WAP 网关和工具包。
Nokia:Nokia Toolkit 和 Nokia WAP Server。
Ericsson:Ericsson R320 和 WapIDE。
UpPhone:UpPhone SDK。
Motorola:Motorola ADK。

3. 开发 WAP 应用一定要有 WAP 手机吗?

  不是,当开发 WAP 应用的时候,不一定需要 WAP 手机。模拟器可以帮助开发者解决大部分的问题。但是
如果是开发商业网站,特别是想知道各种移动电话在显示 WML 页面上的差别的时候,最好是配备一个。目
前各种手机对 WML 标记的支持和中文的支持状况大不相同,因此 WAP 手机还是必要的。

4. 开发者需要一个 WAP 网关吗?

  不是很必要。如果只想进行简单的 WAP 内容服务,可以使用现有的 Web 服务器(只需要修改 MIME 类
型)。移动电话会通过坐落在本地的网关连接到你的服务器上。
  但是在网关上驻留开发者的程序有很多好处。既然开发者的程序是网关的一个部分,开发者就可以知
道呼叫号码、身份、位置等等。

5. 可以看到 WML 的源代码么?

   如果开发者使用 SDK 浏览的时候将能够看到 WML 的代码。如果只有一个 HTML 浏览器,可以访问
“Fetch Page”服务(http://www.webcab.de)来取得代码。这个可以显示在 Internet 上的任何 WML 页面
中。

6. 可能在 WML 中加入 applets 吗?

     不能。

7. 可以使用 HTML 开发工具来开发 WAP 应用吗?

    在大多数情况下开发工具是使用基于 PC 的浏览器。HTML、JavaScript 和 Java 对于 WAP 开发来说都没
有用处。但是,越来越多的开发工具在加入对 WML 的支持。
    Allair 的 Cold Fusion 4.5 和 HomeSite 已经有 WML 支持,虽然 Allair 也许需要清除一些 BUG。另外
PHP 和 ASP 在 Coldfusion/HomeSite 也能支持。
    可以到 Marjolei Katsma 的 HomeSite Help site 上得到更多的信息。

8. 可以通过 WML 页面来操作数据库吗?
                                第 1 页 共 23 页
可以,与创建 HTML 页面相同。任何相关的服务器端的技术都可以用来生成 WML 页面。

9. 可以使用 CGI 生成 WML 页面吗?

  当然。可以用创建 HTML 同样的方法来创建 WML。如果想书写一个 CGI 来创建 WML,只要记住在页面的开
头正确设置 MIME 类型。具体的形式根据所使用的语言不同而不同。例如在 Perl 中:

print ("Content-type:application/vnd.wap.wml nnn"); 

     注意至少要使用 2 个换行。

10. 如何使用 Cold Fusion 来生成页面?

     使用 Cold Fusion 只需要加上:

     <CFCONTENT type="text/vnd.wap.wml">

11. 如何使用 PHP 来书写动态的 WML 页面?

  PHP(和大多数其他服务端脚本语言一样)可以被用来书写动态的 WML 内容。只需要将输出的标记限
制在 WML 微型浏览器可接受的范围内。
  注意 PHP 有很多内建的 HTML 功能,特别是错误功能,这些功能 WML 微型浏览器可能无法识别。
  PHP 同样可以在一个 HTML 文件中编写出既适合于 HTML,也适合于 WML 的内容。PHP 的源代码对于客户
端来说是不可见的。因此可以针对 HTML 浏览器输出 HTML 页面,针对 WML 浏览器输出 WML 页面。
  可以在开发 PHP 编写的 WML 页面的时候把以下代码加在开头:

<?

// header("Content-type: text/vnd.wap.wml");
  echo("<?xml version="1.0"?>n");
echo("<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
//"http://www.wapforum.org/DTD/wml_1.1.xml">nn");
?>

  基于 PC 的浏览器将忽略这些无法理解的 WML 标记。但是如果想在 WAP 设备或者模拟器上测试的时候,
只需要将"//"去掉,页面自动变成 WML 页面。

12. 使用 PHP 动态输出 WML

  这些例子生成一个非常有用的应用叫做:PizzaCalc。它将输入所有的 pizza 的帐单和人的数目,可
以算出每个人的花费。
  应用生成一个动态的页面叫做“calc”或者“input”。                 注意到所有的转义字符例如双引号。该页显示
了一个简单的变量处理,和如何传递参数到另外的卡片:
  使用 WML 浏览器就可以测试应用程序:
    http://wap.colorline.no/wap-faq/apps/pizzacalc.html。
  或者输入:
    http://wap.colorline.no/demos.html 选择应用。


                                           第 2 页 共 23 页
<?
header("Content-type: text/vnd.wap.wml");
echo("<?xml version="1.0"?>n");
echo("<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">nn");
echo("<!--The application PizzaCalc was originally made by The Crusaders
www.crusaders.no on the Commodore Amiga -->n");
echo("<!-- It was unfortunately not possible to emulate the crap interger handling of the
original program -->n");
?>

<wml>
<?
  if($action == "calc") {
    echo("<card id="result" title="PizzaCalc">n");
    echo("<do type="prev" label="Back">n");
    echo("<go href="pizzacalc.html#input"/>n");
    echo("</do>n");
    echo("<p>n");
    echo("The cost per eater will be ".$total / $eaters."<br/>n");
  }
  else {
    echo("<card id="input" title="PizzaCalc">n");
    echo("<p>n");
echo("<anchor>Split Pizza bill
<go href="pizzacalc.html?total=$(total)&eaters=$(eaters)&action=calc"/>
</anchor>n");
    echo("<br/>n");
    echo("Total cost: <input type="text" name="total" format="*N"/>n");
    echo("Eaters: <input type="text" name="eaters" format="*N"/>n");
  }
?>
</p>
</card>
</wml>

13. 可以使用 Java Servlet 来生成 WML 页面吗?

  当然。  可以使用创建 HTML 同样的方法来创建 WML。             如果想书写一个 CGI 来创建 WML,只要记住在页面的
开头正确设置 MIME 类型:
  response.setContentType("text/vnd.wap.wml");

14. 可以使用 ASP、Perl 等生成动态的应用吗?

    是的。可以使用任何服务器端的脚本语言来生成 WAP 应用。

15. 如何使用 ASP 书写 WML 内容?


                                       第 3 页 共 23 页
ASP(Active Server Pages)可以做到和 PHP 一样,也可以用来书写动态的 WML。如果需要一些好的
例子请参考 Luca Passani's WAP and ASP articles。或者查看 Jean-Luc Praz's
(jeanluc@corobori.com)。更多的 ASP 例子在:http://www.corobori.com/wap/。

16. 在使用 ASP 动态输出 WML 页面的时候,已经设置了 Content-type,但是浏览器返回的仍然是 text/html,有什么问题
吗?


     如果在 ASP 脚本中有一个错误,那么诊断程序会发还一个 HTML 页面,请检查脚本。

17. 在使用 ASP 生成 WML 页面的时候出现了错误: <MIME type "text/html" is not supported>,会是什么问题?


     这个问题是 Web 浏览器不知道 WML 的正确类型,修改 ASP 的第一行,加入:

     <Response.ContentType = "text/vnd.wap.wml"> 

     后就可以工作了。

18. 下面的代码有什么问题吗?

<%Response.ContentType = "text/vnd.WAP.WML"%>
<?xml version="1.0"?>

     去掉<?xml version="1.0"?>之前的空格。XML 解释器希望在这行中没有其他字符,甚至是空行。

19. ASP 代码可以在模拟器上工作,在真正的浏览器上怎么不行?

    在很多模拟器上没有像真正的 WML 浏览器那么严格。这些对于那些没有使用网关的模拟器(Nokia
SDK/Toolkit)来说更是这样,有些就根本没有使用网关(WinWAP、WapMAN)。
    一个真正的 WML 浏览器应该只读取二进制的数据(从 WML 编码得来的)WMLC,对于网关应该将文本
WML 转换/编译成 WMLC。语法是非常严格的。ASP 是为 HTML 浏览器设置的,但是 HTML 没有 WML 那么严格。
    这里在 ASP 生成动态页面的时候有一个微小的“bug”。    它在 WML 浏览器上不允许有任何地方输出白行
(例如:空格,回车,换行)。     注意到有些网关可能会修正这些问题,但有的则不管(例如:CMG 网关)。
    下面是一个常见的 ASP 代码用来输出 WML 页面开头的 MIME 类型:

<%Response.ContentType = "text/vnd.wap.wml"%>
<?xml version="1.0"?>

    问题就在 ASP 将会在 .wml"%> 和 <?xml vers 之间输出换行和回车。这两行就被分割了。这将打乱
WML 代码的内容。 必须以“<”开头,而且第一行是<?xml version="1.0"?>。
            WML                                    就上面的 WML 页面回车/
换行将会出现问题。
    最简单的解决办法是:

     <%Response.ContentType = "text/vnd.wap.wml"%><?xml version="1.0"?>

     在 XML 定义正确的格式化以后,后面的部分 WML 对空格就没有那么严格的要求。

   要注意的是有些网关在输出 ASP 的时候会有问题,因此在 WML 代码中最好使用 Response.Write 而不
是<%=MyVar%>。

                                        第 4 页 共 23 页
20. 如何使用 Perl 来生成 WML 内容?

   和其他 Server 端程序一样。Perl 也可以用来书写漂亮的 WAP 应用程序。
   最常见的就是如何使用 Perl 输出正确的 MIME 类型,下面的例子说明了这一点:

print "Content-type: text/vnd.wap.wmlnn";
print "<?xml version="1.0"?>n";
print "<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">n";
print "<wml>n";
……

21. 应当如何下手书写 WAP 应用程序?

    其实需要的只是 Text 编辑器。但是使用一个开发工具可以节约很多时间。
    在这之前应该浏览一下 WAP 的权威站点:www.wapforum.com。
    在 Nokia WAP 开发论坛中进行注册,并且下载 Nokia WAP Developer Toolkit 。Toolkit 中的 PDF 文
件可以给出一定的 WML 和 WMLScript 指导。Nokia Toolkit 需要 JRE (Java Runtime Environment)
v.1.2.2 或者更高版本。
    虽然工具可以用来为 WAP 设备设计应用,但是不是为专门的移动电话。在 WAP 开发工具上所看到的并
不代表用户在手机上所看到的。为了确定想看到的事情,最好需要一个 WAP 设备,例如移动电话,或者模
拟器。
    Nokia WAP SDK 2 有一个 7110 的模拟器。模拟器是一个有效的检测方式,能检测程序中的 bug。 Nokia
SDK 同样还包括一个小的 WAP server 让开发者可以从本地或者 HTTP 服务器上下载 WML 页面。
    到 Phone.com 开发站点注册后,Phone.com 提供 UP.browser。这是最流行的浏览器,特别是在美国,
Phone.com 提供 UP.SDK。 在注册之后就可以下载。
    对于 Ericsson R320 和 R380 是最近的事情。 应该注册并查看 Ericsson's Developer's Zone 来得到
开发工具。R380 是一个非常好的模拟器,在 Symbian 不需要注册就可以下载。Ericsson 没有公开的为
R320 的模拟器。
    Motorola 有一个平台叫做 Mobile Internet eXchange 或者 MIX 。Mobile Application
Development Kit 已经开发出一个开发平台,即为 WAP 也为 Motorola 的 VoxML。     在注册后,可以在下面的
网址找到数据包。

   http://www.motorola.com/MIMS/MSPG/cgi-bin/spn_madk.cgi. 

  WAPmine 是一个独立的应用,叫做 WAPPage 是一个所见即所得的编辑工具。而且有一个 XML 树型控
件来编辑 WML 标签。
  如果在开发公共应用程序时,想在很多设备上测试你的程序,就像在不同的浏览器上测试 HTML 页面
一样。注意在不同的 WML 浏览器上的差别,可能比在不同的 HTML 浏览器上的差别要大。

22. 如何编写和测试 WML 页面?

    现在有很多 SDK。AnywhereYouGo.com 有 WAP SDK 和 IDE 列表,可以下载一个来用。任何文本编辑器都
可以书写一个简单的 WML 页面,当然 HTML 编辑器也可以(特别是那些支持个人定义标签的),例如:
Allaire Homesite (http://www.allaire.com )。可以使用 SDK 来做简单的测试,但是对于大的项目可
能要困难些。AnywhereYouGo.com 已经建立一套基于 Web 的工具来帮助 WAP 测试。

23. 哪儿可以在找到 WML 的测试工具?

                                       第 5 页 共 23 页
首先确定 WML 代码是正确的,然后再使用 WML 测试工具。
  有一个非常好的测试工具在 Zygo Communications(http://wap.z-y-g-o.com/tools/),测试工具
是用 Perl 写的。里面还有其他的工具可供下载。

24. 如何操作 WML 页面?

  操作 WML 页面或者卡片,最简单的办法是通过现有的网关。大多数移动电话提供者将功能都放在主页
上,在上面可以通过 WAP 设备操作。网关的链接一般叫做“Go to URL”。当选择以后,WAP 设备将通过网
关操作指定的普通 IP 或者 URL。在这种情况下,网关读取从 WAP 设备发送给网关的 WML 内容,就像 PC 浏览
器读取内容的过程一样。
  有些营运商选择不让他们的用户操作其他的站点。这个就像 Internet Service Provider 只允许用户
操作 ISP 自己的站点。像这样的做法是不明智的,这样会发现自己的用户去其他地方了。
  如果要坚持这种方法,可以通过 ISP 拨号或者使用一个公共的网关来取得其他的 WAP 资源。

25. 有没有一个友好的方式来管理 WML 内容?

   还没有。虽然 Oracale 正在开发数据库驱动的文档服务,被称为 Panama,可以支持 WAP 分发。

26. 如何防止用户代理 cache 页面?

   如果用户使用 ASP,应该加入一行<%Response.expires=-1%> ,这个将阻止 Cache。

27. 怎样防止从 Cache 中读取 WML 页面?

  当 WML 页面下载到 WAP 设备后,它将保存在 WAP 设备内存中一段时间,直到这个时间过期。在这之后,
页面将从服务器下载,而不是从 WAP 设备的缓存读取。这个过程被称做 Cache。
  但是有些时候不想让页面从缓存中读取,而是从服务器端读取。一个典型的例子就是当服务器的内容
不断在更新的时候,通过在 HTTP 头中加入一定的 cache 信息,来告诉 WAP 设备该页面将不存储在缓存中。
  可以在服务器端生成 HTTP 头,或者使用 PHP、  ASP、Perl 或者其他服务端开发语言。这一行不能被包括
在页面里,既然是 HTTP 的信息头,就不是 WML 元素。
  对于静态页面,或许没有使用服务器端脚本语言,许多浏览器支持 META 标签来控制浏览器的 Cache。
看本部分的最后的例子。
  将下面代码加入到 HTTP 头中,页面将马上过期:

Expires: Mon, 26 Jul 1997 05:00:00 GMT
Last-Modified: DD. month YYYY HH:MM:SS GMT
Cache-Control: no-cache, must-revalidate
Pragma: no-cache

    第一行告诉微型浏览器,页面已经过期一段时间了。第二行告诉浏览器页面最后一次修改的时间。DD
应该换成当天的日期,month YY HH MM SS 等等类推。第三行和第四行有同样的效果。告诉浏览器页面不被
Cache(第三行适用于 HTTP 1.1,第四行适用于 HTTP 1.0)。
    下面的是 PHP 的一个例子:

<?
// set the correct MIME type
     header("Content-type: text/vnd.wap.wml");
// expires in the past
     header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
                                       第 6 页 共 23 页
// Last modified, right now
     header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); 
// Prevent caching, HTTP/1.1
     header("Cache-Control: no-cache, must-revalidate");
// Prevent caching, HTTP/1.0
     header("Pragma: no-cache");
   ?>

   下面是使用 WebClasses(VB)的例子。使用"Response.Expires=-1",防止 Cache。

 Private Sub WebClass_Start()
      'Set correct MIME type
      Response.ContentType = "text/vnd.wap.wml"
     
      'Make sure no caching
      Response.Expires = -1
      Response.AddHeader "Pragma", "no-cache"
      Response.AddHeader "Cache-Control", "no-cache, must-revalidate"
   
      'Use basicwml(my own) as template
      Set NextItem = basicwml
  End Sub 

   这里有一个 ASP 的例子,同样使用“Response.Expires=-1”防止 Cache。

<%
      Response.ContentType = "text/vnd.wap.wml"
      Response.Expires = -1
      Response.AddHeader "Pragma", "no-cache"
      Response.AddHeader "Cache-Control", "no-cache, must-revalidate"
%> 

   最后是使用 META 的例子:

<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
  <wml>
    <head>
      <meta forua="true" http-equiv="Cache-Control" content="max-age=0"/>
    </head>
    <card id="alway***pire">
      <p>This deck will never be stored in the cache</p>
    </card>
  </wml>

   下面的页面是在经过 86400 秒(24 hours)后过期。


                                      第 7 页 共 23 页
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
  <wml>
    <head>
      <meta forua="true" http-equiv="Cache-Control" content="max-age=86400"/>
    </head>
    <card id="expire1day">
      <p>This card will live in the cache for a day</p>
    </card>
  </wml>

  有些浏览器例如:UP.Simulator 如果可以通过“返回”达到另外一个卡片,那么它将不会重新装载
卡片。为了强制这个更新动作,用户必须在 META 标签中使用 must-revalidate 参数。

   <meta forua="true" http-equiv="Cache-Control" content="must-revalidate"/>

28. 如何防止变量被保存在 Cache 中?

  变量保存在 Cache 中,这样变量还可以再利用。例如当用户返回到上一个输入卡片,他不需要重新输
入,只需要改变需要改变的地方。但是在某些情况下这会造成一些问题。例如以 WAP 聊天系统,有些变量
用了一遍又一遍,但是需要不同的内容。有些浏览器,例如:Nokia 7110,就会存在类似的在该清除的时
候无法清除的问题。
  在 WML 中,<card>标签有一个参数叫做 newcontext。
  当 newcontext="true" 时清除所有的变量。但是这样也清除了所有导航的历史记录,这意味着 back
按钮不再工作。
  为了清除变量,可以告诉浏览器将变量设为空:

<setvar name="one_variable" value=""/>
<setvar name="another_variable" value=""/>

    但是,不是每个时候都有效果。在某些情况下必须使用一个难以想象的方法来清空变量。就是使用
onenterforward 事件。

<onevent type="onenterforward">
   <refresh>
     <setvar name="one_variable" value=""/>
     <setvar name="another_variable" value=""/>
   </refresh>
</onevent>

29. 怎么能够知道请求是从 WML 浏览器来的还是 HTML 浏览器来的?

  既然要利用已经存在的为 HTML 浏览器编写的代码,就需要知道请求是从 HTML 浏览器还是从 WML 浏览
器过来的。同样地,如果想重新引导的 HTML 浏览器直接到相应的 HTML 文档上,WML 浏览器到 WML 页面上,
以下的 PHP 代码就可以做到这些。




                                       第 8 页 共 23 页
<?
// Because this script sends out HTTP header information,
// the first characters in the file must be the <? PHP tag.

// relative URL to your HTML file
   $htmlredirect = "/html/my_htmlpage.html";
// ABSOLUTE URL to your WML file 
   $wmlredirect = "http://wap.mysite.com/wml/my_wmldeck.wml";

   if(strpos(strtoupper($HTTP_ACCEPT),"VND.WAP.WML") > 0)
{// Check whether the browser/gateway says it accepts WML.
     $br = "WML";
   }
   else {
     $browser=substr(trim($HTTP_USER_AGENT),0,4);
     if($browser=="Noki" || // Nokia phones and emulators
        $browser=="Eric" || // Ericsson WAP phones and emulators
        $browser=="WapI" || // Ericsson WapIDE 2.0
        $browser=="MC21" || // Ericsson MC218
        $browser=="AUR " || // Ericsson R320
        $browser=="R380" || // Ericsson R380
        $browser=="UP.B" || // UP.Browser
        $browser=="WinW" || // WinWAP browser
        $browser=="UPG1" || // UP.SDK 4.0
        $browser=="upsi" || // another kind of UP.Browser ??
        $browser=="QWAP" || // unknown QWAPPER browser
        $browser=="Jigs" || // unknown JigSaw browser
        $browser=="Java" || // unknown Java based browser
        $browser=="Alca" || // unknown Alcatel-BE3 browser (UP based?)
        $browser=="MITS" || // unknown Mitsubishi browser
        $browser=="MOT-" || // unknown browser (UP based?)
        $browser=="My S" || // unknown Ericsson devkit browser ?
$browser=="WAPJ" || // Virtual WAPJAG www.wapjag.de
$browser=="fetc" || // fetchpage.cgi Perl script from www.wapcab.de
$browser=="ALAV" || // yet another unknown UP based browser ?
        $browser=="Wapa") // another unknown browser (Web based "Wapalyzer"?)
        {
        $br = "WML";
     }
     else {
       $br = "HTML";
     }
   }

   if($br == "WML") {
// Force the browser to load the WML file instead
    header("302 Moved Temporarily");
    header("Location: ".$wmlredirect);
    exit;
                                       第 9 页 共 23 页
   }
   else {
// Force the browser to load the HTML file instead
    header("302 Moved Temporarily");
    header("Location: ".$htmlredirect);
    exit;
   }
  ?> 

    这个判断是在服务端完成的, PHP 代码将首先查看网关是否接收 text/vnd.wap.vml MIME 类型。      如果
不是,将检测前面的字符,查看是否为 WML 浏览器。                如果不符合,那么就假设为 HTML 浏览器。如果有新的
WML 浏览器,那么 ID 字符串也要增加。
    这个代码基于 Robert Whitinger(robert@wapsight.com)的代码,使用了 Don
Amaro(donamaro.concepcion@nl.unisys.com)提供的列表。
    注意:由于只需要四个字符串就可以辨别,因此例如:"WapIDE-SDK/2.0;(R320s(Arial))" 可以使
用“WapI”来代替是可行的做法,也是足够的。
    同样的功能也可以通过 ASP 来解决。先判断请求的是“/index.wml” 或者 “/index.html” 和所需
要的 MIME 类型。   另外以下的脚本辨别的方式和上面不一样。            另外还需要网关告诉服务器它能接收 的 text/
vnd.wap.wml MIME 类型。该例子如下所示:

<%
Response.Buffer = TRUE
  Dim IsWap
  httpAccept = LCase(Request.ServerVariables("HTTP_ACCEPT"))
  if Instr(httpAccept,"wap") then
  IsWap=1
  Else Response.Redirect "/index.html" : Response.Flush : Response.End
End if
%>
<%Response.ContentType = "text/vnd.wap.wml"%><?xml version="1.0"?>
<%Response.Flush%>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
  <wml>
  <card id="redirect">
  <onevent type="onenterforward">
  <go href="/index.wml"/>
  </onevent>
  <p>
  <a href="/index.wml">enter</a>
  </p>
  </card>
  </wml>
  <%Response.Flush:Response.End%>

30. 如何判断访问者是来自哪个浏览器或者移动电话?

  可以通过检查 HTTP_USER_AGENT 标签来判断。例如试着使用 Microsoft Internet Explorer 访问一个
站点的时候,HTTP_USER_AGENT 将返回:Mozilla/4.0 (compatible;MSIE 5.0; Windows 98);在同
                                      第 10 页 共 23 页
样的情况下使用 Nokia 7110 访问这个站点,HTTP_USER_AGENT 就会是:Nokia7110/1.0(04.73)。据此可
以判断用户代理是什么类型的。

31. 可以得到用户代理的电话号码吗?

    不可以,除非网关支持这个特点,WAP 没有办法知道用户的电话号码。

32. 可以通过 WML 使得可以用 WAP 设备进行拨号吗?

    WAP 的电话功能可以使用 Wireless Telephony Application Interface(WTAI)。

    例如:

        WMLScript: WTAPublic.MakeCall("9287787"); 

    但是第一代的 WAP 设备不支持这个功能。

33. 能够从 WAP 设备中读取数据吗,例如:电话号码?

    这里有一些通过 HTTP 的信息,但是十分有限。              既然只有网关发送过来少量的信息,像 WAP 设备的号码
可能无法读取。同时,在某些国家这还涉及到个人隐私的问题。
    基本上丢弃的内容就是 WAP 网关传送给 HTTP 服务器的内容。这不同于 WAP 网关到网关。Phone.com 的
UP.Link 网关是一个最好的例子。因为它在 HTTP 头中返回一个字符串叫做 UP_X_SUBNO,里面包含了电话
号码。Ericsson 网关将传送一个辨别设备用的字符串,但是在明文中没有电话号码。
    每次 WAP 设备向 HTTP 服务器请求一个 URL,WAP 网关就会将信息传送给 HTTP 服务器。
    以下的 PHP 脚本显示了从网关过来的所有 HTTP 头的信息。可以使用 WML 浏览器进行测试。
(http://wap.colorline.no/clientinfo.html)。其他的例子也可以在下面的 UTL 中找到:
http://wap.colorline.no/demos.html
    第一个部分是取得所有的标准 HTTP 头信息。第二个部分是提取一个内容。

<?
  header("Content-type: text/vnd.wap.wml");
  echo("<?xml version="1.0"?>n");
echo("<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">nn");
  echo("<!—Code written in Microsoft NOTEPAD.EXE à n");
?>

<wml>
  <card id="init" title="Client Info">
    <p>
      <?
        // First part – standard HTTP stuff
        $headers = getallheaders();
        while (list($header, $value) = each($headers)) {
          echo strtoupper($header). ": ". $value. "<br/>n";       
        }
        // Second part

                                      第 11 页 共 23 页
// IP address of the client side
        echo("REMOTE_ADDR: ".$REMOTE_ADDR. "<br/>n");
// Port at the client side
        echo("REMOTE_PORT: ".$REMOTE_PORT. "<br/>n");
// Name of authenticated user
        echo("REMOTE_USER: ".$REMOTE_USER. "<br/>n");
// Gateway Interface type
        echo("GATEWAY_INTERFACE: ".$GATEWAY_INTERFACE. "<br/>n");
// Protocol used by the server
        echo("SERVER_PROTOCOL: ".$SERVER_PROTOCOL. "<br/>n");
// Request Method
        echo("REQUEST_METHOD: ".$REQUEST_METHOD. "<br/>n");
// Connection type
        echo("HTTP_CONNECTION: ".$HTTP_CONNECTION. "<br/>n");
// Host it connected via (proxy)
        echo("HTTP_VIA: ".$HTTP_VIA. "<br/>n");
      ?>
    </p>
  </card>
</wml> 

    Henrik Gemal (gemal@dk.net)也有一个在线的基于 WML 的工具 BrowserSpy,来显示更多关于 HTTP
头的信息、服务器环境和用户的浏览器等等。有关这个工具的详细情况可以浏览 http://wap.gemal.dk/
    Werner Forkel 提交了一个 Perl 的脚本,可以显示电话号码(如果有)。可以在以下位置测试:
http://wap.colorline.no/wap-faq/apps/subnotest.wml,同样也收集在:
http://wap.colorline.no/demos.html.
    这些程序只适合某个网关。如果要测试其他的网关,可能就显示不出电话号码。因此电话号码不能作
为 ID 号来处理。至少因为不是一个全球的标准。

34. 有没有办法连接到电话号码?

  在某些情况下,当在显示了一连串的号码之后,需要中断功能连接到一个电话号码上并拨号。例如:
执行一个 dial:12345678 就非常像 mailt 标签。
  越来越多的浏览器都支持这个功能,但还不是所有。Phone.com, Mitsubishi 和 Ericsson 已经在浏
览器中集成了这个基于 Wireless Telephony Interface specifications (WTAI)的功能。 WTAI 将允许
以下的 URL 将关闭连接并且拨号:

  <go href="wtai://wp/mc;+4712345678">Make a call to +47-12345678</go> 

  Nokia 7110 已经有个功能叫做“Use Number”。它可以通过 WML 卡片查找一个类似于电话号码的列
表,然后用户可以选择进行呼叫。注意用户必须分离这些数字以便它能正常工作。

35. 使用 GET 或者 POST 方式能传送多少字符?

  使用 GET 或者 POST 方式所能传送的字符数目,不同的设备有不同的限制。   一个 GET 通过 UTL 传送变量,
能传送的数据总量比使用 POST 方式所能传送的数据要小。例如,Nokia 7110 似乎对每个 GET 限制在 512
个字节左右,但是 POST 最大可以达到一个编译后卡片的大小(约 1300 字节)。UP.SDK 4.0 将 GET 请求限
制在 970 左右,最大可以达到一个编译后卡片的大小。
  显然,卡片有时候保存了要发送给服务器的参数的内容,既然编译后的卡片大小有限制,那么肯定
                                     第 12 页 共 23 页
要影响到整个所能传输的数据。
  在 POST 和 GET 之间没有太多的区别。比如这个没有很好地使用 GET 的例子。

<input type="text" name="var1" format="*N"/>
   <p>
     <anchor>Send it
     <go href="somescript.cgi?variable=$(var1)" method="get"/>
     </anchor>
   </p>

  下面仍然是一个使用 GET 的请求,但是使用了<postfield>来传送参数。这个代码就漂亮多了。既然可
以定义为 GET,同样也很容易转成 POST。

<input type="text" name="var1" format="*N"/>
   <p>
     <anchor>Send it
     <go href="somescript.cgi" method="get">
       <postfield name="variable" value="$(var1)"/>
     </go>
     </anchor>
   </p>

   直接改为 POST:

<input type="text" name="var1" format="*N"/>
   <p>
     <anchor>Send it
     <go href="somescript.cgi" method="post">
       <postfield name="variable" value="$(var1)"/>
     </go>
     </anchor>
   </p>

   最好是做测试找到到底能传输多少数据。这里有个测试程序:

http://wap.colorline.no/wap-faq/apps/putsize.php3。

  这个程序也可以在下面的 URL 中找到:http://wap.colorline.no/demos.html。
  该程序将产生一个卡片包含一个变量,里面包含了一定数量的字符 X。用户可以选择传输是使用 GET
还是 POST。在传输之后,脚本将要显示接收到的字符个数。
  脚本生成一个页面来测试使用 GET 或者 POST 方式到底能发送多少个字符:

<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
  <head>
  <meta forua="true" http-equiv="Cache-Control" content="max-age=0"/>
  <meta forua="true" http-equiv="Cache-Control" content="must-revalidate"/>
                                      第 13 页 共 23 页
  </head>
  <card>
  <do type="prev" label="Back">
  <go href="putsize.php3"/>
  </do>
  <p>
  <anchor>GET data
  <go method="get" href="putsize.php3">
  <postfield name="a"
value="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"/>
  </go>
  </anchor>
  </p>
  </card>
</wml>

36. 如何同 HTML 站点一样 POST/CGI,返回表单数据到服务器?

   如果使用:

       <go method="post" href="mycgi.cgi"> 

   并且使用:

       <postfield name="fieldname" value="$NameOfInputField"/> 

   就可以 POST 数据给 CGI 程序了。

37. POST 无法工作是怎么回事?

    有很多说 POST 参数将会丢失的流言,特别是在 Nokia 7110。就笔者所知,还没有哪个 Nokia 7110 有
这样的问题。这个问题主要是存在于网关或接收方。
    测试显示 Nokia SDK 2.18,当使用内建网关的时候,使用 POST 会出现问题。甚至当 method 设置成
“POST”的时候,服务器那边还是将 POST 请求作为 GET。
    当使用 POST 的 URL 时 ,Nokia SDK 将会崩溃。在某些情况下 URL 的最后的字符将被删除。
    POST Test 页面将简单的 POST 的两个变量叫做“var1”和“var2”来显示整个变量的内容和 HTTP 头
的内容。如果不能看到正确的变量内容,肯定有问题。检查 HTTP 头中的 application/x-www-form-
urlencoded(注意!需要在变量中输入一些内容)。
    这个方法解决了 Nokia SDK 2.18 的问题,可以把它配置到任意的公共网关来测试。笔者推荐使用
wapHQ 网关。
    在其他的情况下,POST 确实不工作,问题可能是 HTTP 头在服务器端解释的时候有问题。脚本语言,
例如:ASP、Java 或是 CGI 等等都是通过查看在 HTTP 头中的 application/x-www-form-urlencoded 完全
匹配的字符串。       在某些情况下字符串可能有附加的数据,例如:charset="utf8" 。      既然服务器端不是精确
的匹配,它就不会查看 HTTP 头,因此 POST 就变量丢失了。
    注意这不是浏览器的问题,在 HTTP 头加入字符集描述,将造成脚本语言方面的错误。
    为了检测有关网关或浏览器的问题,仍使用上面的 POST Test 页面来测试。           同样查看 application/x-
www-form-urlencoded 的输出,检查有没有附加的字符在结尾部分,如果有,那么这就是服务器端的问
题。
    解决这个问题的方案很复杂,它随用户使用的脚本描述语言不同而不同,而且需要操作原代码。简单
                                      第 14 页 共 23 页
地说,解决方案就是需要人工读取 HTTP 头,不要使用脚本语言已经写好的读取方式。
  这里有一个用 ASP 编写的解决方法。它显示了如何在 POST 中抓取数据。用户需要从二进制数据中发现
需要的变量。

Dim lngToalByteCount
Dim vntRequestData

  lngTotalByteCount = Request.TotalBytes
  vntRequestData = Request.BinaryRead(lngTotalByteCount)

    全部的代码,就应该像下面的代码:

<%@ Language=VBScript %>
<%
  Dim Temp, i, sPost, sWMLDeck

  'Converts the binary data to a string.
  For i = 1 To Request.TotalBytes
    Temp = Request.BinaryRead(1)
    sPost = sPost & Chr(AscB(Temp))
  Next

    'Parses out the values of the POSTED variables (in this
    'example myvar1 and myvar2).
    Dim sVar1, sVar2
    sVar1 = getVar("myvar1", sPost)
    sVar2 = getVar("myvar2", sPost)

    'Writes the WML Deck displaying the POSTED Variables
    sWMLDeck = "<?xml version=""1.0""?>" & vbCrLf
    sWMLDeck = sWMLDeck & "<!DOCTYPE wml PUBLIC ""-//WAPFORUM//DTD WML 1.1//EN"" "
    sWMLDeck = sWMLDeck & """http://www.wapforum.org/DTD/wml_1.1.xml"">" & vbCrLf
    sWMLDeck = sWMLDeck & vbCrLf & "<wml>" & vbCrLf & vbTab
    sWMLDeck = sWMLDeck & "<card id=""main"" title=""POST TEST"">" & vbCrLf
    sWMLDeck = sWMLDeck & vbTab & vbTab & "<p>" & vbCrLf
    sWMLDeck = sWMLDeck & vbTab & vbTab & vbTab & "myVar1: " & sVar1 & "<br/>" & vbCrLf
    sWMLDeck = sWMLDeck & vbTab & vbTab & vbTab & "myVar2: " & sVar2 & vbCrLf
    sWMLDeck = sWMLDeck & vbTab & vbTab & "</p>" & vbCrLf & vbTab
    sWMLDeck = sWMLDeck & "</card>" & vbCrLf & ">/wml>"

  Response.ContentType = "text/vnd.wap.wml"
  Response.Write(sWMLDeck)

  'Quick function for picking out the values of the POSTed variables.
  'sKey is the variable name, sRaw is the POST string.
  Private Function getVar(sKey, sRaw)
  Dim sRetVal
If InStr(sRaw, sKey) Then
sRetVal = Mid(sRaw, InStr(sRaw, sKey) + Len(sKey) + 1)
                                       第 15 页 共 23 页
If InStr(sRetVal, "&") Then
sRetVal = Mid(sRetVal, 1, InStr(sRetVal, "&") - 1)
End If
End If
getVar = sRetVal
  End Function
%>

38. 为什么 META 标签不工作?

   浏览器不支持默认的 meta 标签,例如:

   <meta http-equiv="refresh" content="1;http://somewhere.com/"> 

  虽然有少量网关支持非常有限的 META 标记。   但是测试显示,如果使用了它们,网关就会出问题。       例如
某网关不支持普通的 HTTP Cache 控制,如果要实现 Cache 控制只好使用特殊的 META 标记。显然从其他网
关来的用户就可能不支持这个 META。注意:不要使用 META tags。肯定有其他的方式来完成你的想法。

   最常使用的 META 是:

   <meta http-equiv="refresh" content="1;http://somewhere.com/"> 

   这个告诉浏览器重新装入指定的 WML 页面。WML 中已经包含了一个<ontimer>。

39. 为什么服务器接收不到用户发送的参数?

    用户输入的参数或者其他参数可以像在 HTML 中一样通过提交方式发送到服务器。在 HTML 中这个是
<FORM>,POST 或者 GET。
    首先知道要知道 POST 和 GET 的区别。对于 POST 浏览器将生成一个数据包将变量名和它们的内容捆绑
在一起,并发送到服务器。对于 GET,它其实是一个 URL 请求,变量名和内容都包含在 URL 中。
    对于 WAP 环境,要求是非常严格的,必须要根据协议来操作。虽然以下的 URL

   "/cgi-bin/somescript?username=john&telephone=123-123-1234&occupation=banana+bender"

  可以在 HTML 环境中工作,但是在 WAP 环境中无法工作。    以上的部分编码将使得保护的变量内容被误解。
特殊的空格(在 banana 和 bender )被转成 “+”。 URL 就根本没有空格。
  以上的 URL 在 WAP 中无法工作的主要原因是用来分割每个变量和变量内容的 & (与号)没有转义。   正
确的格式应该是:

    "/cgi-bin/somescript?
username=john&amp;telephone=123-123-1234&amp;occupation=banana+bender"

   在这里 & 被名字实体所替换。为了解释更清楚些,请看下面的代码:

<card id="input" title="Gimme some data">
  <p><input type="text" name="username" format="M*m"/></p>
  <p><input type="text" name="occupation" format="M*m"/></p>
<p>
<anchor>Send this
                                      第 16 页 共 23 页
<go href="/cgi-bin/somescript?username=$(username)
&amp;occupation=$(occupation)"/>
</anchor>
</p>

   注意这不是真正的 WAP 协议,专门的字符应该转义,否则将得到不可预料的结果。

40. 为什么在 HTTP 中的 Referer 看不见?

  当 HTML 浏览器从一个 URL 到另外一个 URL 的时候,它默认地会发送一个叫做 Referer 的 HTTP 头给
服务器,告诉它在浏览这个页面之前的那个页面。这是一个非常有用的特点,在 WAP 环境中同样也有。但
是既然这个信息来自用户代理(浏览器)、WAP 设备,通常为了节约带宽和时间,就被省略了。
  为了使用 Referer ,应该使用新的 URL 标签例如: <a>,<go>等等,并且加入参数:sendreferer。

       <go href="/somedir/somedeck.wml" sendreferer="true"/> 

   这样就会把参考的 URL 发送到服务器。

41. 如果没有找到 URL,有可能重新将用户引导到另外一个 WML 卡片或者页面吗?

   是的。但这是服务器端的特点,与客户端没有关系。

42. 为什么普通的 HTTP 302 重新导向不好使?

    这的确是一个事实。核心的问题是在服务端的脚本语言,而不是在服务端语言和服务器之间。
    所谓的 302 Found HTTP 反应是指服务器告诉用户代理,它所需要的资源在另外的地方可以找到。302
反应可能包括一个人们可理解的信息,如果在这种情况下“ Content-type: ”就被设置了。笔者所测试
过的服务器,即使没有内容也都加了“Content-type:”。           默认的 “Content-type:” 是 text/html。当然
有些网关不喜欢这个类型。
    以下的例子已经经过测试,在 Apache 和 Microsoft Internet Information Server 都可以工作。    如果
使用其他的 Web Server,或者其他的脚本语言,需要能转换这些简单的脚本。                     关键的工作是十分简单的,
除非需要,不用告诉服务器整个 HTTP 头。       大多数 Web Server 将自动完成这个 HTTP 头,使得用户代理可以
理解。
    所有的代码例子可以在线测试。        如果它们能够工作,用户将被重新引导到 http://wap.colorline.no/
clientinfo.html ,在那儿将产生一个 WML 页面来显示所有的 HTTP 头。
    PHP 代码测试可以在 http://wap.colorline.no/wap-faq/apps/302test.php3 中找到。

<?
    header("Location: http://wap.colorline.no/clientinfo.html");
    header("Content-type: text/vnd.wap.wml";
?> 

   Perl 测试代码可以在 http://wap.colorline.no/cgi-bin/302test.pl 中找到。 

print "Location: http://wap.colorline.no/clientinfo.htmln";
print "Content-type: text/vnd.wap.wmln"; 

   ASP 测试代码可以在 http://www.colorline.no/302test.asp 中找到。 (注意不同的 URL): 

                                      第 17 页 共 23 页
<%
      Response.Redirect = "http://wap.colorline.no/clientinfo.html";
      Response.ContentType = "text/vnd.wap.wml";
      Response.Flush
      Response.End
%>

43. 可能在 WML 中实现 ASP Session 吗?

  不可能。   可以把信息存储在临时变量中模拟 Session。Session 是保存在用户 PC 上的“cookies”中。目
前的 WAP 设备不支持“cookies”。不过下一代的设备和 WML 可能支持“cookies”。

44. WAP 支持 Session 吗?

    在 HTML 中,一个十分普遍的“处理”用户的方法就是为每个用户分配一个“session”。这个有时候
是通过指定一个独一无二的 cookies 来实现的。然而 WAP 的资源非常有限,因此 session 的处理必须以不
同的方式来处理。
    Alex Kriegel 提供了一个安装在 WAPlinks 的 Custom Session Object 包。这个 zip 文件中包含了 VB
类的文件和编译过的 Dll 文件,还有相关的文档。这些可以在
http://www.waplinks.com/customsessionobject.zip 下载。
    另外一种方法是使用 PHPlib ,它是使用 PHP 编写的。
    Tarique (tarique@nagpur.dot.net.in) 提供了如何使用 PHPlib 来验证和处理每个 WAP 用户。 有相关
的文件和注释可以到下面地址下载:

   http://wap.colorline.no/wap-faq/archive/phplib_wml.zip

45. 可以在 WAP 中使用 Cookies 吗?

  在理论上是可以的,但不是所有的 WAP 设备都支持。另一个方法来管理会话是使用隐藏的 fields(包
含会话标识,无论是 POST 或者 GET 方式)。

46. WAP 支持 Cookies 吗?

  普通的 HTTP Cookies 是作为 WAP 的扩展来实现的。无论你以前听到什么,Cookies 的支持将越来越好。
实际上 Phone.com 的 UP.Link 网关已经支持这个功能有一段时间了。
  可以使用以下的脚本语言检测 Cookie-support,:
      http://wap.colorline.no/wap-faq/apps/cookietest.php3
  脚本在 http://wap.colorline.no/demos.html 也可以得到。
  当第一次看见卡片的时候,记数器应该为 0。                  所有的 Cache 都被关闭。   卡片通过在 URL 中随机地加入变
量来强制自己加载(笔者不推荐这种强制加载办法)。当点击增加计数连接,页面将重新加载,卡片就再
次出现,并且记数器变成 1。
  在脚本中,Cookie 的名字被称做 TestCookie,它有很长的生命期,因此可以隔好几天再来查看记数
器,它将是上一次的数值。         这要求你能使用与上一次访问所使用的 WAP 环境一样,否则将把你的数值清 0。
  如果记数装置一直都是 0,那么 cookie 就没有能传送到你的 Web Server。这个脚本也能表示 Cookie
是否被传送。
  另外,这个脚本同样还显示 HTTP 头中的 HTTP_VIA 和 HTTP_USER_AGENT 。这些能够得到所使用的网
关和模式。一些网关使用 HTTP_VIS 标识自己,而另外一些使用 HTTP_USER_AGENT,还有一些则让程序无法
知道。

                                     第 18 页 共 23 页
下面是它的 PHP 代码。 一个标准的 PHP setcookie() 函数只有在这种脚本语言中才会出现。函数只是
简单地设置 cookie,并且 PHP 变量 $HTTP_COOKIE_VARS 用来读取 cookie。

<?
if(isset($HTTP_COOKIE_VARS["TestCookie"]))
{// Check if TestCookie is set
      $cookieset = "set";

// Read the Cookie
      $cookieid = $HTTP_COOKIE_VARS["TestCookie"];
  // and increase its value
      $cookieid++;
     }
    else {
  // cookie was not set
      $cookieset = "not set";
  // start counter at zero
      $cookieid = 0;
    }
  // apply the Cookie to the HTTP header
 setcookie("TestCookie",$cookieid);
  // set the content type for WML
    header("Content-type: text/vnd.wap.wml");

// disable ALL caching
    header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
    header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
    header("Cache-Control: no-cache, must-revalidate");          
    header("Pragma: no-cache");

    echo("<?xml version="1.0"?>n");
 echo("<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
 "http://www.wapforum.org/DTD/wml_1.1.xml">nn");
 echo("<!-- This application attempts to test the capabilities of a WAP gateway to support
cookies -->n");
    echo("<!-- App by Espen.Lyngaas@colorline.no (c) 2000 -->n");
  // Generate random value for reload forcing
    $random = mt_rand(100000,999999);
 ?>
  <wml>
  <head>

// Even more cache disabling
<meta forua="true" http-equiv="Cache-Control" content="must-revalidate"/> 
  </head>
  <card id="init" title="CookieTest">
  <p>
   Cookie "TestCookie" was <?echo($cookieset)?>.
   Value is currently "<?echo($cookieid)?>"
                                      第 19 页 共 23 页
  </p>
  <p>

<anchor>
Increase value
<go method="get" href="<?echo($PHP_SELF)?>?random=<?echo($random)?>"/>
</anchor>
</p>
<p>Gateway: 
  <?
    if(isset($HTTP_VIA))
{ // Is there something in the HTTP_VIA variable?
      echo($HTTP_VIA);
    }
    else {
      if(isset($HTTP_USER_AGENT))
{ // Is there something in the HTTP_USER_AGENT variable?
        echo($HTTP_USER_AGENT);
      }
      else {
// Absolutely no identifier was found
        echo("Unknown");
      }
    }
  ?>
  </p>
  </card>
  </wml>

47. 如何使用 WAP 设备发送 E-Mail?

  在 HTML 中有一个默认的 E-Mail 机制:“ mailt” 。但在 WML 中不好使,因此 E-Mails 必须通过 WML
表单来解决。例如:

<wml>
     <card id="edit" title="Email Editor">
      <p>From: <input type="text" name="from" format="*M"/></p>
      <p>T <input type="text" name="to" format="*M"/></p>
      <p>Subject: <input type="text" name="subject" format="*M"/></p>
      <p>Message body: <input type="text" name="body" format="*M"/></p>
      <p>
        <anchor>Send this mail
          <go method="post" href="http://some.host/mailhandler"?action=send/">
            <postfield name="from" value="$(from)"/>
            <postfield name="to" value="$(to)"/>
            <postfield name="subject" value="$(subject)"/>
            <postfield name="body" value="$(body)"/>
          </go>
       </anchor>
                                      第 20 页 共 23 页
      </p>
   </card>
</wml> 

  在代码中的 http://some.host/mailhandler 是一个 CGI 程序,它是服务端的脚本程序,将提交的表
单转换成 E-Mail 格式并发送出去。
  如果想使用一个类似于发信的过程,就需要编辑变量名。另外发送的数据是有限的,长信息可能需要
打断。
  为了演示它是如何工作的,下面的 PHP 脚本可以用来处理 Mail。它将格式化 WML 页面,告诉用户是
否发出信件。在真实的应用中,应该加入检测,例如:E-Mail 的合法格式。

<?
// Tell the client that this is a WML deck
    header("Content-type: text/vnd.wap.wml");
    echo("<?xml version="1.0"?>n");
    echo("<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">n");
// The name of your mail server
    $mailer = "wap.colorline.no";
// Format the from field
    $from = $from." (WAP user at ".$mailer.")";

// Add the from field and some character handling to the extra headers
  $extraheaders = $from."nContent-Type: text/plain;
charset=iso-8859-1nContent-Transfer-Encoding: 8bit";

// Start sending out the WML deck
    echo("<wml>n");
    if(mail($to,$subject,$body,$extraheaders))
{// Use PHP's internal mail functionality
// Mail was successfully sent
      echo("<card id="sent" title="Mail sent">n");
      echo("<p>Mail was sent successfully</p>n");
      echo("</card>n");
    }
    else {
// The mail could not be sent
      echo("<card id="notsent" title="Mail failed">n"); 
      echo("<p>Unable to send mail</p>n");
      echo("</card>n");
    }
    echo("</wml>n");
?>

   因为安全性的原因,以上的代码没有演示程序。

48. 可以在模拟器上操作本地的页面,却没有办法访问 Internet 上的,有什么问题吗?


                                      第 21 页 共 23 页
大多数模拟器和工具都可以浏览 Internet、 Intranet 和本机的页面。  但是在访问一些大公司页面的时
候,必须通过代理服务器来取得进入 Internet 的权限。如果必须通过这个代理服务器来取得 HTML 页面,
那么你的 WAP 模拟器也会取得权限来访问 Internet。
    注意到有些模拟器不支持代理服务器,但是大多数是支持的。在模拟器里面设置这些是很简单的。用
户所做的只需要将代理主机的名字、IP 地址和端口号输入就可以了。如果没有找到,你可以在
systems/network 管理器里面设置这些,也可以检查 Netscape/IE 的设置。
    在某些情况下,代理服务器使用 userid 和 password 来取得进入 Internet 的权限。有些模拟器支
持用户代理服务器,用户应该能告诉模拟器相关的代理配置。
    在极少的情况下,使用代理服务器(如 Microsoft Proxy Server,)的用户会遇到更多的问题。  这个
代理服务器只接受一种验证方式(userid/password)。这种验证被称做 NTLM ,并且是某种 MS 的验证
方式。几乎很少有模拟器支持这种方式。因此最好是避免使用它,或者让管理员使用“Basic
Authentication”方式以避免更多的麻烦。

49. 什么是 PUSHing,它是如何工作的?

    PUSH 被加入到 WAP 1.2,而且只在 WAP 1.2 中才存在。简单地来说,PUSH 提供了另外一种从服务器向
用户发送数据的方式。PULLing 是从客户端请求信息,然后接收它;PUSH 意味着服务器可以向用户发送数
据,而不需要用户来请求。
    内容或者应用服务器无法向用户代理直接发送数据,必须使用一种叫做 Push Proxy 的网关。PPG 是
基于 Internet 的 Push Initiator (内容或者应用服务器) 与移动用户之间的。在 Internet 一边,使用
Push Access Protocol,在移动网络一边使用 Push Over-the-Air Protocol。
    当前只有 WAP 1.2 开发平台支持 PUSH, 例如 Nokia Toolkit 2.0。 Nokia Toolkit 2.0 only 内
部支持 PUSHing,意味着用户可以从工具包的界面将消息推送到模拟器。如果想试着到一个外部的 Push
Proxy Gateway, 工具包就崩溃了。从 readme 文件中知道,PUSHing 还没有经过完整的测试。

50. WAP 模拟器说 text/html 不支持,但是用户的 MIME 设置是正确的,为什么?

  当使用服务端的脚本语言,例如 ASP、PHP 或者 Perl,来生成 WML 输出,或者从 HTTP 服务器提供 WML
页面的时候。记住 HTTP 一般默认的显示是 HTML,其 MIME 类型是 text/html。
  如果 HTTP 服务器或者服务器脚本有错误,错误的信息将使用 HTML 显示,因此微型浏览器是不能显示
错误信息的。
  一个开发工具/模拟器可以让用户看到从 HTTP 服务器过来的代码。          例如,在 Nokia SDK 中,这个功能
被称做 View Source。通过看代码可以知道 HTTP 服务器到底发送了些什么内容。也可以使用普通的浏览器
来查看任何 HTML 格式的错误信息。

51. 在哪儿有 Visio 移动电话的模板库?

   目前唯一知道的就是它包含在 Nokia 7110 中。

52. 有没有其他有用的 WML 内容服务列表?

  这里至少有一个。
  对于 Unix 用户, http://pwot.co.uk/wml/中有 Thomas Neill (ponder@pwot.co.uk)提供的 WML
工具,包括 WML 二进制编译和反编译。
  Angus 和 Zygo WAP(angus@z-y-g-o.com)已经开发出了一个 Perl 工具包。       它还在为管道式的 WML 编
译器工作。

53. XML 到 XSL 的转换可以应用到 WML 和 WAP 吗?

                                第 22 页 共 23 页
既然 WML 实际上是 XML,并且 XSL 将 WML 转换成其他不同的 XML 文档,那么问题的答案是显然的:XSL
也可以应用到 WML。可以参考 Luca Passani 的文章《WebTechniques 。这个文章在网络上的地址是 :
                                                           》
    http://www.webtechniques.com/archives/2000/03/passani/
    它推荐看一下叫做        《在 Apache 下 Cocoon 计划的实现》这篇文章。           “Cocoon 是一个依赖于新的 W3C 技
术(例如 DOM,XML,和 XSL)框架。         Cocoon 计划在于改变 Wen 信息创建,生成和提供的方式。           文档内容、   风
格和逻辑经常因为个人或者工作组的不同而不同。 Cocoon 目标在于将这三层分离,允许三层次之间进行
独立的设计,创建和管理,减少相互之间的影响,增加工作的可复用性以及缩短上市的时间。Web 内容的
产生大多数是基于 HTML 的,但是 HTML 并不能将三者分离开来,混合着各种格式标签,程序逻辑等等。而
Cocoon 计划将要改变这种情况,允许内容,逻辑和风格相互分离。使用 XML 来保存,但是使用 XSL 来将它
们混合。”
    基本上来说,Cocoon 将解读 HTTP 头,判断使用的是什么浏览器,然后使用不同的风格来选择正确的
页面,使用 XSL 进行混合。

54. 想让用户只要简单地按下一个按钮就能够转跳到其他卡片而不是通过选择 URL,这个可能吗?

   不,不可能。

55. 如何避免一个行的中断以便可以在一行中输入多个链接?

   在 Nokia 7110 中,不可能做到这一点,每个链接都占据自己的一行。




                                  第 23 页 共 23 页

Más contenido relacionado

Similar a Wap开发问答大全

四天学会Ajax
四天学会Ajax四天学会Ajax
四天学会Ajax
mornone
 
移动页面(Wap)制作的基础实践
移动页面(Wap)制作的基础实践移动页面(Wap)制作的基础实践
移动页面(Wap)制作的基础实践
sunnylqm
 
Axis1.4 开发指南 V1.0
Axis1.4 开发指南 V1.0Axis1.4 开发指南 V1.0
Axis1.4 开发指南 V1.0
yiditushe
 
重构之道 触屏篇
重构之道 触屏篇重构之道 触屏篇
重构之道 触屏篇
麦哥UE
 
2012 java two-desktop-appliction-using-j-ruby-with-swt
2012 java two-desktop-appliction-using-j-ruby-with-swt2012 java two-desktop-appliction-using-j-ruby-with-swt
2012 java two-desktop-appliction-using-j-ruby-with-swt
tka
 
淘宝彩票移动项目开发实践
淘宝彩票移动项目开发实践淘宝彩票移动项目开发实践
淘宝彩票移动项目开发实践
alvis-m
 
Ajax新手快车道
Ajax新手快车道Ajax新手快车道
Ajax新手快车道
yiditushe
 
非常靠谱 Html 5
非常靠谱 Html 5 非常靠谱 Html 5
非常靠谱 Html 5
Tony Deng
 
HTML5 Web workers
HTML5 Web workersHTML5 Web workers
HTML5 Web workers
Tom Fan
 

Similar a Wap开发问答大全 (20)

利用Signalr打造即時通訊@Tech day geek
利用Signalr打造即時通訊@Tech day geek利用Signalr打造即時通訊@Tech day geek
利用Signalr打造即時通訊@Tech day geek
 
Wap2.0
Wap2.0Wap2.0
Wap2.0
 
Wap2.0
Wap2.0Wap2.0
Wap2.0
 
NodeJS基礎教學&簡介
NodeJS基礎教學&簡介NodeJS基礎教學&簡介
NodeJS基礎教學&簡介
 
四天学会Ajax
四天学会Ajax四天学会Ajax
四天学会Ajax
 
四天学会Ajax
四天学会Ajax四天学会Ajax
四天学会Ajax
 
拆分初始化负载
拆分初始化负载拆分初始化负载
拆分初始化负载
 
test
testtest
test
 
移动页面(Wap)制作的基础实践
移动页面(Wap)制作的基础实践移动页面(Wap)制作的基础实践
移动页面(Wap)制作的基础实践
 
Axis1.4 开发指南 V1.0
Axis1.4 开发指南 V1.0Axis1.4 开发指南 V1.0
Axis1.4 开发指南 V1.0
 
重构之道 触屏篇
重构之道 触屏篇重构之道 触屏篇
重构之道 触屏篇
 
Bluemix Node-Red Part I
Bluemix Node-Red Part IBluemix Node-Red Part I
Bluemix Node-Red Part I
 
Web base 吴志华
Web base 吴志华Web base 吴志华
Web base 吴志华
 
2012 java two-desktop-appliction-using-j-ruby-with-swt
2012 java two-desktop-appliction-using-j-ruby-with-swt2012 java two-desktop-appliction-using-j-ruby-with-swt
2012 java two-desktop-appliction-using-j-ruby-with-swt
 
淘宝彩票移动项目开发实践
淘宝彩票移动项目开发实践淘宝彩票移动项目开发实践
淘宝彩票移动项目开发实践
 
Ajax新手快车道
Ajax新手快车道Ajax新手快车道
Ajax新手快车道
 
非常靠谱 Html 5
非常靠谱 Html 5 非常靠谱 Html 5
非常靠谱 Html 5
 
Wap Portal
Wap PortalWap Portal
Wap Portal
 
Spring 2.0 技術手冊第七章 - Spring Web MVC 框架
Spring 2.0 技術手冊第七章 - Spring Web MVC 框架Spring 2.0 技術手冊第七章 - Spring Web MVC 框架
Spring 2.0 技術手冊第七章 - Spring Web MVC 框架
 
HTML5 Web workers
HTML5 Web workersHTML5 Web workers
HTML5 Web workers
 

Más de yiditushe

Spring入门纲要
Spring入门纲要Spring入门纲要
Spring入门纲要
yiditushe
 
J Bpm4 1中文用户手册
J Bpm4 1中文用户手册J Bpm4 1中文用户手册
J Bpm4 1中文用户手册
yiditushe
 
性能测试实践2
性能测试实践2性能测试实践2
性能测试实践2
yiditushe
 
性能测试实践1
性能测试实践1性能测试实践1
性能测试实践1
yiditushe
 
性能测试技术
性能测试技术性能测试技术
性能测试技术
yiditushe
 
Load runner测试技术
Load runner测试技术Load runner测试技术
Load runner测试技术
yiditushe
 
J2 ee性能测试
J2 ee性能测试J2 ee性能测试
J2 ee性能测试
yiditushe
 
面向对象的Js培训
面向对象的Js培训面向对象的Js培训
面向对象的Js培训
yiditushe
 
Flex3中文教程
Flex3中文教程Flex3中文教程
Flex3中文教程
yiditushe
 
开放源代码的全文检索Lucene
开放源代码的全文检索Lucene开放源代码的全文检索Lucene
开放源代码的全文检索Lucene
yiditushe
 
基于分词索引的全文检索技术介绍
基于分词索引的全文检索技术介绍基于分词索引的全文检索技术介绍
基于分词索引的全文检索技术介绍
yiditushe
 
Lucene In Action
Lucene In ActionLucene In Action
Lucene In Action
yiditushe
 
Lucene2 4学习笔记1
Lucene2 4学习笔记1Lucene2 4学习笔记1
Lucene2 4学习笔记1
yiditushe
 
Lucene2 4 Demo
Lucene2 4 DemoLucene2 4 Demo
Lucene2 4 Demo
yiditushe
 
Lucene 全文检索实践
Lucene 全文检索实践Lucene 全文检索实践
Lucene 全文检索实践
yiditushe
 
Lucene 3[1] 0 原理与代码分析
Lucene 3[1] 0 原理与代码分析Lucene 3[1] 0 原理与代码分析
Lucene 3[1] 0 原理与代码分析
yiditushe
 
7 面向对象设计原则
7 面向对象设计原则7 面向对象设计原则
7 面向对象设计原则
yiditushe
 
10 团队开发
10  团队开发10  团队开发
10 团队开发
yiditushe
 
9 对象持久化与数据建模
9  对象持久化与数据建模9  对象持久化与数据建模
9 对象持久化与数据建模
yiditushe
 
8 Uml构架建模
8  Uml构架建模8  Uml构架建模
8 Uml构架建模
yiditushe
 

Más de yiditushe (20)

Spring入门纲要
Spring入门纲要Spring入门纲要
Spring入门纲要
 
J Bpm4 1中文用户手册
J Bpm4 1中文用户手册J Bpm4 1中文用户手册
J Bpm4 1中文用户手册
 
性能测试实践2
性能测试实践2性能测试实践2
性能测试实践2
 
性能测试实践1
性能测试实践1性能测试实践1
性能测试实践1
 
性能测试技术
性能测试技术性能测试技术
性能测试技术
 
Load runner测试技术
Load runner测试技术Load runner测试技术
Load runner测试技术
 
J2 ee性能测试
J2 ee性能测试J2 ee性能测试
J2 ee性能测试
 
面向对象的Js培训
面向对象的Js培训面向对象的Js培训
面向对象的Js培训
 
Flex3中文教程
Flex3中文教程Flex3中文教程
Flex3中文教程
 
开放源代码的全文检索Lucene
开放源代码的全文检索Lucene开放源代码的全文检索Lucene
开放源代码的全文检索Lucene
 
基于分词索引的全文检索技术介绍
基于分词索引的全文检索技术介绍基于分词索引的全文检索技术介绍
基于分词索引的全文检索技术介绍
 
Lucene In Action
Lucene In ActionLucene In Action
Lucene In Action
 
Lucene2 4学习笔记1
Lucene2 4学习笔记1Lucene2 4学习笔记1
Lucene2 4学习笔记1
 
Lucene2 4 Demo
Lucene2 4 DemoLucene2 4 Demo
Lucene2 4 Demo
 
Lucene 全文检索实践
Lucene 全文检索实践Lucene 全文检索实践
Lucene 全文检索实践
 
Lucene 3[1] 0 原理与代码分析
Lucene 3[1] 0 原理与代码分析Lucene 3[1] 0 原理与代码分析
Lucene 3[1] 0 原理与代码分析
 
7 面向对象设计原则
7 面向对象设计原则7 面向对象设计原则
7 面向对象设计原则
 
10 团队开发
10  团队开发10  团队开发
10 团队开发
 
9 对象持久化与数据建模
9  对象持久化与数据建模9  对象持久化与数据建模
9 对象持久化与数据建模
 
8 Uml构架建模
8  Uml构架建模8  Uml构架建模
8 Uml构架建模
 

Wap开发问答大全

  • 1. WAP(wml)开发 faq --摘自 csdn 1. 开 发 WAP 软 件 需 要 哪 些 工 具 ? 为了开发 WAP 应用程序,需要一个 WAP 网关(注意:这里的网关可能是指支持 WML 的服务器。可以通 过配置 WWW 服务器达到这个目的)和 WAP 工具包。工具包应当包括模拟器和能让开发者浏览 WML 网页。WML 页面的开发和 HTML 页面的开发一样,可以使用 Notepad 或者其他文本编辑器来进行编辑。 2. 有哪些公司现在提供这样的开发环境? Nokia、Ericsson、UpPhone 和 Motorola 都提供免费的 WAP 网关和工具包。 Nokia:Nokia Toolkit 和 Nokia WAP Server。 Ericsson:Ericsson R320 和 WapIDE。 UpPhone:UpPhone SDK。 Motorola:Motorola ADK。 3. 开发 WAP 应用一定要有 WAP 手机吗? 不是,当开发 WAP 应用的时候,不一定需要 WAP 手机。模拟器可以帮助开发者解决大部分的问题。但是 如果是开发商业网站,特别是想知道各种移动电话在显示 WML 页面上的差别的时候,最好是配备一个。目 前各种手机对 WML 标记的支持和中文的支持状况大不相同,因此 WAP 手机还是必要的。 4. 开发者需要一个 WAP 网关吗? 不是很必要。如果只想进行简单的 WAP 内容服务,可以使用现有的 Web 服务器(只需要修改 MIME 类 型)。移动电话会通过坐落在本地的网关连接到你的服务器上。 但是在网关上驻留开发者的程序有很多好处。既然开发者的程序是网关的一个部分,开发者就可以知 道呼叫号码、身份、位置等等。 5. 可以看到 WML 的源代码么? 如果开发者使用 SDK 浏览的时候将能够看到 WML 的代码。如果只有一个 HTML 浏览器,可以访问 “Fetch Page”服务(http://www.webcab.de)来取得代码。这个可以显示在 Internet 上的任何 WML 页面 中。 6. 可能在 WML 中加入 applets 吗? 不能。 7. 可以使用 HTML 开发工具来开发 WAP 应用吗? 在大多数情况下开发工具是使用基于 PC 的浏览器。HTML、JavaScript 和 Java 对于 WAP 开发来说都没 有用处。但是,越来越多的开发工具在加入对 WML 的支持。 Allair 的 Cold Fusion 4.5 和 HomeSite 已经有 WML 支持,虽然 Allair 也许需要清除一些 BUG。另外 PHP 和 ASP 在 Coldfusion/HomeSite 也能支持。 可以到 Marjolei Katsma 的 HomeSite Help site 上得到更多的信息。 8. 可以通过 WML 页面来操作数据库吗? 第 1 页 共 23 页
  • 2. 可以,与创建 HTML 页面相同。任何相关的服务器端的技术都可以用来生成 WML 页面。 9. 可以使用 CGI 生成 WML 页面吗? 当然。可以用创建 HTML 同样的方法来创建 WML。如果想书写一个 CGI 来创建 WML,只要记住在页面的开 头正确设置 MIME 类型。具体的形式根据所使用的语言不同而不同。例如在 Perl 中: print ("Content-type:application/vnd.wap.wml nnn");  注意至少要使用 2 个换行。 10. 如何使用 Cold Fusion 来生成页面? 使用 Cold Fusion 只需要加上: <CFCONTENT type="text/vnd.wap.wml"> 11. 如何使用 PHP 来书写动态的 WML 页面? PHP(和大多数其他服务端脚本语言一样)可以被用来书写动态的 WML 内容。只需要将输出的标记限 制在 WML 微型浏览器可接受的范围内。 注意 PHP 有很多内建的 HTML 功能,特别是错误功能,这些功能 WML 微型浏览器可能无法识别。 PHP 同样可以在一个 HTML 文件中编写出既适合于 HTML,也适合于 WML 的内容。PHP 的源代码对于客户 端来说是不可见的。因此可以针对 HTML 浏览器输出 HTML 页面,针对 WML 浏览器输出 WML 页面。 可以在开发 PHP 编写的 WML 页面的时候把以下代码加在开头: <? // header("Content-type: text/vnd.wap.wml");   echo("<?xml version="1.0"?>n"); echo("<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" //"http://www.wapforum.org/DTD/wml_1.1.xml">nn"); ?> 基于 PC 的浏览器将忽略这些无法理解的 WML 标记。但是如果想在 WAP 设备或者模拟器上测试的时候, 只需要将"//"去掉,页面自动变成 WML 页面。 12. 使用 PHP 动态输出 WML 这些例子生成一个非常有用的应用叫做:PizzaCalc。它将输入所有的 pizza 的帐单和人的数目,可 以算出每个人的花费。 应用生成一个动态的页面叫做“calc”或者“input”。 注意到所有的转义字符例如双引号。该页显示 了一个简单的变量处理,和如何传递参数到另外的卡片: 使用 WML 浏览器就可以测试应用程序: http://wap.colorline.no/wap-faq/apps/pizzacalc.html。 或者输入: http://wap.colorline.no/demos.html 选择应用。 第 2 页 共 23 页
  • 3. <? header("Content-type: text/vnd.wap.wml"); echo("<?xml version="1.0"?>n"); echo("<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">nn"); echo("<!--The application PizzaCalc was originally made by The Crusaders www.crusaders.no on the Commodore Amiga -->n"); echo("<!-- It was unfortunately not possible to emulate the crap interger handling of the original program -->n"); ?> <wml> <?   if($action == "calc") {     echo("<card id="result" title="PizzaCalc">n");     echo("<do type="prev" label="Back">n");     echo("<go href="pizzacalc.html#input"/>n");     echo("</do>n");     echo("<p>n");     echo("The cost per eater will be ".$total / $eaters."<br/>n");   }   else {     echo("<card id="input" title="PizzaCalc">n");     echo("<p>n"); echo("<anchor>Split Pizza bill <go href="pizzacalc.html?total=$(total)&eaters=$(eaters)&action=calc"/> </anchor>n");     echo("<br/>n");     echo("Total cost: <input type="text" name="total" format="*N"/>n");     echo("Eaters: <input type="text" name="eaters" format="*N"/>n");   } ?> </p> </card> </wml> 13. 可以使用 Java Servlet 来生成 WML 页面吗? 当然。 可以使用创建 HTML 同样的方法来创建 WML。 如果想书写一个 CGI 来创建 WML,只要记住在页面的 开头正确设置 MIME 类型: response.setContentType("text/vnd.wap.wml"); 14. 可以使用 ASP、Perl 等生成动态的应用吗? 是的。可以使用任何服务器端的脚本语言来生成 WAP 应用。 15. 如何使用 ASP 书写 WML 内容? 第 3 页 共 23 页
  • 4. ASP(Active Server Pages)可以做到和 PHP 一样,也可以用来书写动态的 WML。如果需要一些好的 例子请参考 Luca Passani's WAP and ASP articles。或者查看 Jean-Luc Praz's (jeanluc@corobori.com)。更多的 ASP 例子在:http://www.corobori.com/wap/。 16. 在使用 ASP 动态输出 WML 页面的时候,已经设置了 Content-type,但是浏览器返回的仍然是 text/html,有什么问题 吗? 如果在 ASP 脚本中有一个错误,那么诊断程序会发还一个 HTML 页面,请检查脚本。 17. 在使用 ASP 生成 WML 页面的时候出现了错误: <MIME type "text/html" is not supported>,会是什么问题? 这个问题是 Web 浏览器不知道 WML 的正确类型,修改 ASP 的第一行,加入: <Response.ContentType = "text/vnd.wap.wml">  后就可以工作了。 18. 下面的代码有什么问题吗? <%Response.ContentType = "text/vnd.WAP.WML"%> <?xml version="1.0"?> 去掉<?xml version="1.0"?>之前的空格。XML 解释器希望在这行中没有其他字符,甚至是空行。 19. ASP 代码可以在模拟器上工作,在真正的浏览器上怎么不行? 在很多模拟器上没有像真正的 WML 浏览器那么严格。这些对于那些没有使用网关的模拟器(Nokia SDK/Toolkit)来说更是这样,有些就根本没有使用网关(WinWAP、WapMAN)。 一个真正的 WML 浏览器应该只读取二进制的数据(从 WML 编码得来的)WMLC,对于网关应该将文本 WML 转换/编译成 WMLC。语法是非常严格的。ASP 是为 HTML 浏览器设置的,但是 HTML 没有 WML 那么严格。 这里在 ASP 生成动态页面的时候有一个微小的“bug”。 它在 WML 浏览器上不允许有任何地方输出白行 (例如:空格,回车,换行)。 注意到有些网关可能会修正这些问题,但有的则不管(例如:CMG 网关)。 下面是一个常见的 ASP 代码用来输出 WML 页面开头的 MIME 类型: <%Response.ContentType = "text/vnd.wap.wml"%> <?xml version="1.0"?> 问题就在 ASP 将会在 .wml"%> 和 <?xml vers 之间输出换行和回车。这两行就被分割了。这将打乱 WML 代码的内容。 必须以“<”开头,而且第一行是<?xml version="1.0"?>。 WML 就上面的 WML 页面回车/ 换行将会出现问题。 最简单的解决办法是: <%Response.ContentType = "text/vnd.wap.wml"%><?xml version="1.0"?> 在 XML 定义正确的格式化以后,后面的部分 WML 对空格就没有那么严格的要求。 要注意的是有些网关在输出 ASP 的时候会有问题,因此在 WML 代码中最好使用 Response.Write 而不 是<%=MyVar%>。 第 4 页 共 23 页
  • 5. 20. 如何使用 Perl 来生成 WML 内容? 和其他 Server 端程序一样。Perl 也可以用来书写漂亮的 WAP 应用程序。 最常见的就是如何使用 Perl 输出正确的 MIME 类型,下面的例子说明了这一点: print "Content-type: text/vnd.wap.wmlnn"; print "<?xml version="1.0"?>n"; print "<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">n"; print "<wml>n"; …… 21. 应当如何下手书写 WAP 应用程序? 其实需要的只是 Text 编辑器。但是使用一个开发工具可以节约很多时间。 在这之前应该浏览一下 WAP 的权威站点:www.wapforum.com。 在 Nokia WAP 开发论坛中进行注册,并且下载 Nokia WAP Developer Toolkit 。Toolkit 中的 PDF 文 件可以给出一定的 WML 和 WMLScript 指导。Nokia Toolkit 需要 JRE (Java Runtime Environment) v.1.2.2 或者更高版本。 虽然工具可以用来为 WAP 设备设计应用,但是不是为专门的移动电话。在 WAP 开发工具上所看到的并 不代表用户在手机上所看到的。为了确定想看到的事情,最好需要一个 WAP 设备,例如移动电话,或者模 拟器。 Nokia WAP SDK 2 有一个 7110 的模拟器。模拟器是一个有效的检测方式,能检测程序中的 bug。 Nokia SDK 同样还包括一个小的 WAP server 让开发者可以从本地或者 HTTP 服务器上下载 WML 页面。 到 Phone.com 开发站点注册后,Phone.com 提供 UP.browser。这是最流行的浏览器,特别是在美国, Phone.com 提供 UP.SDK。 在注册之后就可以下载。 对于 Ericsson R320 和 R380 是最近的事情。 应该注册并查看 Ericsson's Developer's Zone 来得到 开发工具。R380 是一个非常好的模拟器,在 Symbian 不需要注册就可以下载。Ericsson 没有公开的为 R320 的模拟器。 Motorola 有一个平台叫做 Mobile Internet eXchange 或者 MIX 。Mobile Application Development Kit 已经开发出一个开发平台,即为 WAP 也为 Motorola 的 VoxML。 在注册后,可以在下面的 网址找到数据包。 http://www.motorola.com/MIMS/MSPG/cgi-bin/spn_madk.cgi.  WAPmine 是一个独立的应用,叫做 WAPPage 是一个所见即所得的编辑工具。而且有一个 XML 树型控 件来编辑 WML 标签。 如果在开发公共应用程序时,想在很多设备上测试你的程序,就像在不同的浏览器上测试 HTML 页面 一样。注意在不同的 WML 浏览器上的差别,可能比在不同的 HTML 浏览器上的差别要大。 22. 如何编写和测试 WML 页面? 现在有很多 SDK。AnywhereYouGo.com 有 WAP SDK 和 IDE 列表,可以下载一个来用。任何文本编辑器都 可以书写一个简单的 WML 页面,当然 HTML 编辑器也可以(特别是那些支持个人定义标签的),例如: Allaire Homesite (http://www.allaire.com )。可以使用 SDK 来做简单的测试,但是对于大的项目可 能要困难些。AnywhereYouGo.com 已经建立一套基于 Web 的工具来帮助 WAP 测试。 23. 哪儿可以在找到 WML 的测试工具? 第 5 页 共 23 页
  • 6. 首先确定 WML 代码是正确的,然后再使用 WML 测试工具。 有一个非常好的测试工具在 Zygo Communications(http://wap.z-y-g-o.com/tools/),测试工具 是用 Perl 写的。里面还有其他的工具可供下载。 24. 如何操作 WML 页面? 操作 WML 页面或者卡片,最简单的办法是通过现有的网关。大多数移动电话提供者将功能都放在主页 上,在上面可以通过 WAP 设备操作。网关的链接一般叫做“Go to URL”。当选择以后,WAP 设备将通过网 关操作指定的普通 IP 或者 URL。在这种情况下,网关读取从 WAP 设备发送给网关的 WML 内容,就像 PC 浏览 器读取内容的过程一样。 有些营运商选择不让他们的用户操作其他的站点。这个就像 Internet Service Provider 只允许用户 操作 ISP 自己的站点。像这样的做法是不明智的,这样会发现自己的用户去其他地方了。 如果要坚持这种方法,可以通过 ISP 拨号或者使用一个公共的网关来取得其他的 WAP 资源。 25. 有没有一个友好的方式来管理 WML 内容? 还没有。虽然 Oracale 正在开发数据库驱动的文档服务,被称为 Panama,可以支持 WAP 分发。 26. 如何防止用户代理 cache 页面? 如果用户使用 ASP,应该加入一行<%Response.expires=-1%> ,这个将阻止 Cache。 27. 怎样防止从 Cache 中读取 WML 页面? 当 WML 页面下载到 WAP 设备后,它将保存在 WAP 设备内存中一段时间,直到这个时间过期。在这之后, 页面将从服务器下载,而不是从 WAP 设备的缓存读取。这个过程被称做 Cache。 但是有些时候不想让页面从缓存中读取,而是从服务器端读取。一个典型的例子就是当服务器的内容 不断在更新的时候,通过在 HTTP 头中加入一定的 cache 信息,来告诉 WAP 设备该页面将不存储在缓存中。 可以在服务器端生成 HTTP 头,或者使用 PHP、 ASP、Perl 或者其他服务端开发语言。这一行不能被包括 在页面里,既然是 HTTP 的信息头,就不是 WML 元素。 对于静态页面,或许没有使用服务器端脚本语言,许多浏览器支持 META 标签来控制浏览器的 Cache。 看本部分的最后的例子。 将下面代码加入到 HTTP 头中,页面将马上过期: Expires: Mon, 26 Jul 1997 05:00:00 GMT Last-Modified: DD. month YYYY HH:MM:SS GMT Cache-Control: no-cache, must-revalidate Pragma: no-cache 第一行告诉微型浏览器,页面已经过期一段时间了。第二行告诉浏览器页面最后一次修改的时间。DD 应该换成当天的日期,month YY HH MM SS 等等类推。第三行和第四行有同样的效果。告诉浏览器页面不被 Cache(第三行适用于 HTTP 1.1,第四行适用于 HTTP 1.0)。 下面的是 PHP 的一个例子: <? // set the correct MIME type      header("Content-type: text/vnd.wap.wml"); // expires in the past      header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); 第 6 页 共 23 页
  • 7. // Last modified, right now      header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");  // Prevent caching, HTTP/1.1      header("Cache-Control: no-cache, must-revalidate"); // Prevent caching, HTTP/1.0      header("Pragma: no-cache");    ?> 下面是使用 WebClasses(VB)的例子。使用"Response.Expires=-1",防止 Cache。  Private Sub WebClass_Start()       'Set correct MIME type       Response.ContentType = "text/vnd.wap.wml"             'Make sure no caching       Response.Expires = -1       Response.AddHeader "Pragma", "no-cache"       Response.AddHeader "Cache-Control", "no-cache, must-revalidate"           'Use basicwml(my own) as template       Set NextItem = basicwml   End Sub  这里有一个 ASP 的例子,同样使用“Response.Expires=-1”防止 Cache。 <%     Response.ContentType = "text/vnd.wap.wml"     Response.Expires = -1     Response.AddHeader "Pragma", "no-cache"     Response.AddHeader "Cache-Control", "no-cache, must-revalidate" %>  最后是使用 META 的例子: <?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">   <wml>     <head>       <meta forua="true" http-equiv="Cache-Control" content="max-age=0"/>     </head>     <card id="alway***pire">       <p>This deck will never be stored in the cache</p>     </card>   </wml> 下面的页面是在经过 86400 秒(24 hours)后过期。 第 7 页 共 23 页
  • 8. <?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">   <wml>     <head>       <meta forua="true" http-equiv="Cache-Control" content="max-age=86400"/>     </head>     <card id="expire1day">       <p>This card will live in the cache for a day</p>     </card>   </wml> 有些浏览器例如:UP.Simulator 如果可以通过“返回”达到另外一个卡片,那么它将不会重新装载 卡片。为了强制这个更新动作,用户必须在 META 标签中使用 must-revalidate 参数。 <meta forua="true" http-equiv="Cache-Control" content="must-revalidate"/> 28. 如何防止变量被保存在 Cache 中? 变量保存在 Cache 中,这样变量还可以再利用。例如当用户返回到上一个输入卡片,他不需要重新输 入,只需要改变需要改变的地方。但是在某些情况下这会造成一些问题。例如以 WAP 聊天系统,有些变量 用了一遍又一遍,但是需要不同的内容。有些浏览器,例如:Nokia 7110,就会存在类似的在该清除的时 候无法清除的问题。 在 WML 中,<card>标签有一个参数叫做 newcontext。 当 newcontext="true" 时清除所有的变量。但是这样也清除了所有导航的历史记录,这意味着 back 按钮不再工作。 为了清除变量,可以告诉浏览器将变量设为空: <setvar name="one_variable" value=""/> <setvar name="another_variable" value=""/> 但是,不是每个时候都有效果。在某些情况下必须使用一个难以想象的方法来清空变量。就是使用 onenterforward 事件。 <onevent type="onenterforward">    <refresh>      <setvar name="one_variable" value=""/>      <setvar name="another_variable" value=""/>    </refresh> </onevent> 29. 怎么能够知道请求是从 WML 浏览器来的还是 HTML 浏览器来的? 既然要利用已经存在的为 HTML 浏览器编写的代码,就需要知道请求是从 HTML 浏览器还是从 WML 浏览 器过来的。同样地,如果想重新引导的 HTML 浏览器直接到相应的 HTML 文档上,WML 浏览器到 WML 页面上, 以下的 PHP 代码就可以做到这些。 第 8 页 共 23 页
  • 9. <? // Because this script sends out HTTP header information, // the first characters in the file must be the <? PHP tag. // relative URL to your HTML file    $htmlredirect = "/html/my_htmlpage.html"; // ABSOLUTE URL to your WML file     $wmlredirect = "http://wap.mysite.com/wml/my_wmldeck.wml";    if(strpos(strtoupper($HTTP_ACCEPT),"VND.WAP.WML") > 0) {// Check whether the browser/gateway says it accepts WML.      $br = "WML";    }    else {      $browser=substr(trim($HTTP_USER_AGENT),0,4);      if($browser=="Noki" || // Nokia phones and emulators         $browser=="Eric" || // Ericsson WAP phones and emulators         $browser=="WapI" || // Ericsson WapIDE 2.0         $browser=="MC21" || // Ericsson MC218         $browser=="AUR " || // Ericsson R320         $browser=="R380" || // Ericsson R380         $browser=="UP.B" || // UP.Browser         $browser=="WinW" || // WinWAP browser         $browser=="UPG1" || // UP.SDK 4.0         $browser=="upsi" || // another kind of UP.Browser ??         $browser=="QWAP" || // unknown QWAPPER browser         $browser=="Jigs" || // unknown JigSaw browser         $browser=="Java" || // unknown Java based browser         $browser=="Alca" || // unknown Alcatel-BE3 browser (UP based?)         $browser=="MITS" || // unknown Mitsubishi browser         $browser=="MOT-" || // unknown browser (UP based?)         $browser=="My S" || // unknown Ericsson devkit browser ? $browser=="WAPJ" || // Virtual WAPJAG www.wapjag.de $browser=="fetc" || // fetchpage.cgi Perl script from www.wapcab.de $browser=="ALAV" || // yet another unknown UP based browser ?         $browser=="Wapa") // another unknown browser (Web based "Wapalyzer"?)         {         $br = "WML";      }      else {        $br = "HTML";      }    }    if($br == "WML") { // Force the browser to load the WML file instead     header("302 Moved Temporarily");     header("Location: ".$wmlredirect);     exit; 第 9 页 共 23 页
  • 10.    }    else { // Force the browser to load the HTML file instead     header("302 Moved Temporarily");     header("Location: ".$htmlredirect);     exit;    }   ?>  这个判断是在服务端完成的, PHP 代码将首先查看网关是否接收 text/vnd.wap.vml MIME 类型。 如果 不是,将检测前面的字符,查看是否为 WML 浏览器。 如果不符合,那么就假设为 HTML 浏览器。如果有新的 WML 浏览器,那么 ID 字符串也要增加。 这个代码基于 Robert Whitinger(robert@wapsight.com)的代码,使用了 Don Amaro(donamaro.concepcion@nl.unisys.com)提供的列表。 注意:由于只需要四个字符串就可以辨别,因此例如:"WapIDE-SDK/2.0;(R320s(Arial))" 可以使 用“WapI”来代替是可行的做法,也是足够的。 同样的功能也可以通过 ASP 来解决。先判断请求的是“/index.wml” 或者 “/index.html” 和所需 要的 MIME 类型。 另外以下的脚本辨别的方式和上面不一样。 另外还需要网关告诉服务器它能接收 的 text/ vnd.wap.wml MIME 类型。该例子如下所示: <% Response.Buffer = TRUE   Dim IsWap   httpAccept = LCase(Request.ServerVariables("HTTP_ACCEPT"))   if Instr(httpAccept,"wap") then   IsWap=1   Else Response.Redirect "/index.html" : Response.Flush : Response.End End if %> <%Response.ContentType = "text/vnd.wap.wml"%><?xml version="1.0"?> <%Response.Flush%> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">   <wml>   <card id="redirect">   <onevent type="onenterforward">   <go href="/index.wml"/>   </onevent>   <p>   <a href="/index.wml">enter</a>   </p>   </card>   </wml>   <%Response.Flush:Response.End%> 30. 如何判断访问者是来自哪个浏览器或者移动电话? 可以通过检查 HTTP_USER_AGENT 标签来判断。例如试着使用 Microsoft Internet Explorer 访问一个 站点的时候,HTTP_USER_AGENT 将返回:Mozilla/4.0 (compatible;MSIE 5.0; Windows 98);在同 第 10 页 共 23 页
  • 11. 样的情况下使用 Nokia 7110 访问这个站点,HTTP_USER_AGENT 就会是:Nokia7110/1.0(04.73)。据此可 以判断用户代理是什么类型的。 31. 可以得到用户代理的电话号码吗? 不可以,除非网关支持这个特点,WAP 没有办法知道用户的电话号码。 32. 可以通过 WML 使得可以用 WAP 设备进行拨号吗? WAP 的电话功能可以使用 Wireless Telephony Application Interface(WTAI)。 例如: WMLScript: WTAPublic.MakeCall("9287787");  但是第一代的 WAP 设备不支持这个功能。 33. 能够从 WAP 设备中读取数据吗,例如:电话号码? 这里有一些通过 HTTP 的信息,但是十分有限。 既然只有网关发送过来少量的信息,像 WAP 设备的号码 可能无法读取。同时,在某些国家这还涉及到个人隐私的问题。 基本上丢弃的内容就是 WAP 网关传送给 HTTP 服务器的内容。这不同于 WAP 网关到网关。Phone.com 的 UP.Link 网关是一个最好的例子。因为它在 HTTP 头中返回一个字符串叫做 UP_X_SUBNO,里面包含了电话 号码。Ericsson 网关将传送一个辨别设备用的字符串,但是在明文中没有电话号码。 每次 WAP 设备向 HTTP 服务器请求一个 URL,WAP 网关就会将信息传送给 HTTP 服务器。 以下的 PHP 脚本显示了从网关过来的所有 HTTP 头的信息。可以使用 WML 浏览器进行测试。 (http://wap.colorline.no/clientinfo.html)。其他的例子也可以在下面的 UTL 中找到: http://wap.colorline.no/demos.html 第一个部分是取得所有的标准 HTTP 头信息。第二个部分是提取一个内容。 <?   header("Content-type: text/vnd.wap.wml");   echo("<?xml version="1.0"?>n"); echo("<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">nn");   echo("<!—Code written in Microsoft NOTEPAD.EXE à n"); ?> <wml>   <card id="init" title="Client Info">     <p>       <?         // First part – standard HTTP stuff         $headers = getallheaders();         while (list($header, $value) = each($headers)) {           echo strtoupper($header). ": ". $value. "<br/>n";                }         // Second part 第 11 页 共 23 页
  • 12. // IP address of the client side         echo("REMOTE_ADDR: ".$REMOTE_ADDR. "<br/>n"); // Port at the client side         echo("REMOTE_PORT: ".$REMOTE_PORT. "<br/>n"); // Name of authenticated user         echo("REMOTE_USER: ".$REMOTE_USER. "<br/>n"); // Gateway Interface type         echo("GATEWAY_INTERFACE: ".$GATEWAY_INTERFACE. "<br/>n"); // Protocol used by the server         echo("SERVER_PROTOCOL: ".$SERVER_PROTOCOL. "<br/>n"); // Request Method         echo("REQUEST_METHOD: ".$REQUEST_METHOD. "<br/>n"); // Connection type         echo("HTTP_CONNECTION: ".$HTTP_CONNECTION. "<br/>n"); // Host it connected via (proxy)         echo("HTTP_VIA: ".$HTTP_VIA. "<br/>n");       ?>     </p>   </card> </wml>  Henrik Gemal (gemal@dk.net)也有一个在线的基于 WML 的工具 BrowserSpy,来显示更多关于 HTTP 头的信息、服务器环境和用户的浏览器等等。有关这个工具的详细情况可以浏览 http://wap.gemal.dk/ Werner Forkel 提交了一个 Perl 的脚本,可以显示电话号码(如果有)。可以在以下位置测试: http://wap.colorline.no/wap-faq/apps/subnotest.wml,同样也收集在: http://wap.colorline.no/demos.html. 这些程序只适合某个网关。如果要测试其他的网关,可能就显示不出电话号码。因此电话号码不能作 为 ID 号来处理。至少因为不是一个全球的标准。 34. 有没有办法连接到电话号码? 在某些情况下,当在显示了一连串的号码之后,需要中断功能连接到一个电话号码上并拨号。例如: 执行一个 dial:12345678 就非常像 mailt 标签。 越来越多的浏览器都支持这个功能,但还不是所有。Phone.com, Mitsubishi 和 Ericsson 已经在浏 览器中集成了这个基于 Wireless Telephony Interface specifications (WTAI)的功能。 WTAI 将允许 以下的 URL 将关闭连接并且拨号:   <go href="wtai://wp/mc;+4712345678">Make a call to +47-12345678</go>  Nokia 7110 已经有个功能叫做“Use Number”。它可以通过 WML 卡片查找一个类似于电话号码的列 表,然后用户可以选择进行呼叫。注意用户必须分离这些数字以便它能正常工作。 35. 使用 GET 或者 POST 方式能传送多少字符? 使用 GET 或者 POST 方式所能传送的字符数目,不同的设备有不同的限制。 一个 GET 通过 UTL 传送变量, 能传送的数据总量比使用 POST 方式所能传送的数据要小。例如,Nokia 7110 似乎对每个 GET 限制在 512 个字节左右,但是 POST 最大可以达到一个编译后卡片的大小(约 1300 字节)。UP.SDK 4.0 将 GET 请求限 制在 970 左右,最大可以达到一个编译后卡片的大小。 显然,卡片有时候保存了要发送给服务器的参数的内容,既然编译后的卡片大小有限制,那么肯定 第 12 页 共 23 页
  • 13. 要影响到整个所能传输的数据。 在 POST 和 GET 之间没有太多的区别。比如这个没有很好地使用 GET 的例子。 <input type="text" name="var1" format="*N"/>    <p>      <anchor>Send it      <go href="somescript.cgi?variable=$(var1)" method="get"/>      </anchor>    </p> 下面仍然是一个使用 GET 的请求,但是使用了<postfield>来传送参数。这个代码就漂亮多了。既然可 以定义为 GET,同样也很容易转成 POST。 <input type="text" name="var1" format="*N"/>    <p>      <anchor>Send it      <go href="somescript.cgi" method="get">        <postfield name="variable" value="$(var1)"/>      </go>      </anchor>    </p> 直接改为 POST: <input type="text" name="var1" format="*N"/>    <p>      <anchor>Send it      <go href="somescript.cgi" method="post">        <postfield name="variable" value="$(var1)"/>      </go>      </anchor>    </p> 最好是做测试找到到底能传输多少数据。这里有个测试程序: http://wap.colorline.no/wap-faq/apps/putsize.php3。 这个程序也可以在下面的 URL 中找到:http://wap.colorline.no/demos.html。 该程序将产生一个卡片包含一个变量,里面包含了一定数量的字符 X。用户可以选择传输是使用 GET 还是 POST。在传输之后,脚本将要显示接收到的字符个数。 脚本生成一个页面来测试使用 GET 或者 POST 方式到底能发送多少个字符: <?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml"> <wml>   <head>   <meta forua="true" http-equiv="Cache-Control" content="max-age=0"/>   <meta forua="true" http-equiv="Cache-Control" content="must-revalidate"/> 第 13 页 共 23 页
  • 14.   </head>   <card>   <do type="prev" label="Back">   <go href="putsize.php3"/>   </do>   <p>   <anchor>GET data   <go method="get" href="putsize.php3">   <postfield name="a" value="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"/>   </go>   </anchor>   </p>   </card> </wml> 36. 如何同 HTML 站点一样 POST/CGI,返回表单数据到服务器? 如果使用: <go method="post" href="mycgi.cgi">  并且使用: <postfield name="fieldname" value="$NameOfInputField"/>  就可以 POST 数据给 CGI 程序了。 37. POST 无法工作是怎么回事? 有很多说 POST 参数将会丢失的流言,特别是在 Nokia 7110。就笔者所知,还没有哪个 Nokia 7110 有 这样的问题。这个问题主要是存在于网关或接收方。 测试显示 Nokia SDK 2.18,当使用内建网关的时候,使用 POST 会出现问题。甚至当 method 设置成 “POST”的时候,服务器那边还是将 POST 请求作为 GET。 当使用 POST 的 URL 时 ,Nokia SDK 将会崩溃。在某些情况下 URL 的最后的字符将被删除。 POST Test 页面将简单的 POST 的两个变量叫做“var1”和“var2”来显示整个变量的内容和 HTTP 头 的内容。如果不能看到正确的变量内容,肯定有问题。检查 HTTP 头中的 application/x-www-form- urlencoded(注意!需要在变量中输入一些内容)。 这个方法解决了 Nokia SDK 2.18 的问题,可以把它配置到任意的公共网关来测试。笔者推荐使用 wapHQ 网关。 在其他的情况下,POST 确实不工作,问题可能是 HTTP 头在服务器端解释的时候有问题。脚本语言, 例如:ASP、Java 或是 CGI 等等都是通过查看在 HTTP 头中的 application/x-www-form-urlencoded 完全 匹配的字符串。 在某些情况下字符串可能有附加的数据,例如:charset="utf8" 。 既然服务器端不是精确 的匹配,它就不会查看 HTTP 头,因此 POST 就变量丢失了。 注意这不是浏览器的问题,在 HTTP 头加入字符集描述,将造成脚本语言方面的错误。 为了检测有关网关或浏览器的问题,仍使用上面的 POST Test 页面来测试。 同样查看 application/x- www-form-urlencoded 的输出,检查有没有附加的字符在结尾部分,如果有,那么这就是服务器端的问 题。 解决这个问题的方案很复杂,它随用户使用的脚本描述语言不同而不同,而且需要操作原代码。简单 第 14 页 共 23 页
  • 15. 地说,解决方案就是需要人工读取 HTTP 头,不要使用脚本语言已经写好的读取方式。 这里有一个用 ASP 编写的解决方法。它显示了如何在 POST 中抓取数据。用户需要从二进制数据中发现 需要的变量。 Dim lngToalByteCount Dim vntRequestData   lngTotalByteCount = Request.TotalBytes   vntRequestData = Request.BinaryRead(lngTotalByteCount) 全部的代码,就应该像下面的代码: <%@ Language=VBScript %> <%   Dim Temp, i, sPost, sWMLDeck   'Converts the binary data to a string.   For i = 1 To Request.TotalBytes     Temp = Request.BinaryRead(1)     sPost = sPost & Chr(AscB(Temp))   Next   'Parses out the values of the POSTED variables (in this   'example myvar1 and myvar2).   Dim sVar1, sVar2   sVar1 = getVar("myvar1", sPost)   sVar2 = getVar("myvar2", sPost)   'Writes the WML Deck displaying the POSTED Variables   sWMLDeck = "<?xml version=""1.0""?>" & vbCrLf   sWMLDeck = sWMLDeck & "<!DOCTYPE wml PUBLIC ""-//WAPFORUM//DTD WML 1.1//EN"" "   sWMLDeck = sWMLDeck & """http://www.wapforum.org/DTD/wml_1.1.xml"">" & vbCrLf   sWMLDeck = sWMLDeck & vbCrLf & "<wml>" & vbCrLf & vbTab   sWMLDeck = sWMLDeck & "<card id=""main"" title=""POST TEST"">" & vbCrLf   sWMLDeck = sWMLDeck & vbTab & vbTab & "<p>" & vbCrLf   sWMLDeck = sWMLDeck & vbTab & vbTab & vbTab & "myVar1: " & sVar1 & "<br/>" & vbCrLf   sWMLDeck = sWMLDeck & vbTab & vbTab & vbTab & "myVar2: " & sVar2 & vbCrLf   sWMLDeck = sWMLDeck & vbTab & vbTab & "</p>" & vbCrLf & vbTab   sWMLDeck = sWMLDeck & "</card>" & vbCrLf & ">/wml>"   Response.ContentType = "text/vnd.wap.wml"   Response.Write(sWMLDeck)   'Quick function for picking out the values of the POSTed variables.   'sKey is the variable name, sRaw is the POST string.   Private Function getVar(sKey, sRaw)   Dim sRetVal If InStr(sRaw, sKey) Then sRetVal = Mid(sRaw, InStr(sRaw, sKey) + Len(sKey) + 1) 第 15 页 共 23 页
  • 16. If InStr(sRetVal, "&") Then sRetVal = Mid(sRetVal, 1, InStr(sRetVal, "&") - 1) End If End If getVar = sRetVal   End Function %> 38. 为什么 META 标签不工作? 浏览器不支持默认的 meta 标签,例如: <meta http-equiv="refresh" content="1;http://somewhere.com/">  虽然有少量网关支持非常有限的 META 标记。 但是测试显示,如果使用了它们,网关就会出问题。 例如 某网关不支持普通的 HTTP Cache 控制,如果要实现 Cache 控制只好使用特殊的 META 标记。显然从其他网 关来的用户就可能不支持这个 META。注意:不要使用 META tags。肯定有其他的方式来完成你的想法。 最常使用的 META 是: <meta http-equiv="refresh" content="1;http://somewhere.com/">  这个告诉浏览器重新装入指定的 WML 页面。WML 中已经包含了一个<ontimer>。 39. 为什么服务器接收不到用户发送的参数? 用户输入的参数或者其他参数可以像在 HTML 中一样通过提交方式发送到服务器。在 HTML 中这个是 <FORM>,POST 或者 GET。 首先知道要知道 POST 和 GET 的区别。对于 POST 浏览器将生成一个数据包将变量名和它们的内容捆绑 在一起,并发送到服务器。对于 GET,它其实是一个 URL 请求,变量名和内容都包含在 URL 中。 对于 WAP 环境,要求是非常严格的,必须要根据协议来操作。虽然以下的 URL "/cgi-bin/somescript?username=john&telephone=123-123-1234&occupation=banana+bender" 可以在 HTML 环境中工作,但是在 WAP 环境中无法工作。 以上的部分编码将使得保护的变量内容被误解。 特殊的空格(在 banana 和 bender )被转成 “+”。 URL 就根本没有空格。 以上的 URL 在 WAP 中无法工作的主要原因是用来分割每个变量和变量内容的 & (与号)没有转义。 正 确的格式应该是: "/cgi-bin/somescript? username=john&amp;telephone=123-123-1234&amp;occupation=banana+bender" 在这里 & 被名字实体所替换。为了解释更清楚些,请看下面的代码: <card id="input" title="Gimme some data">   <p><input type="text" name="username" format="M*m"/></p>   <p><input type="text" name="occupation" format="M*m"/></p> <p> <anchor>Send this 第 16 页 共 23 页
  • 17. <go href="/cgi-bin/somescript?username=$(username) &amp;occupation=$(occupation)"/> </anchor> </p> 注意这不是真正的 WAP 协议,专门的字符应该转义,否则将得到不可预料的结果。 40. 为什么在 HTTP 中的 Referer 看不见? 当 HTML 浏览器从一个 URL 到另外一个 URL 的时候,它默认地会发送一个叫做 Referer 的 HTTP 头给 服务器,告诉它在浏览这个页面之前的那个页面。这是一个非常有用的特点,在 WAP 环境中同样也有。但 是既然这个信息来自用户代理(浏览器)、WAP 设备,通常为了节约带宽和时间,就被省略了。 为了使用 Referer ,应该使用新的 URL 标签例如: <a>,<go>等等,并且加入参数:sendreferer。 <go href="/somedir/somedeck.wml" sendreferer="true"/>  这样就会把参考的 URL 发送到服务器。 41. 如果没有找到 URL,有可能重新将用户引导到另外一个 WML 卡片或者页面吗? 是的。但这是服务器端的特点,与客户端没有关系。 42. 为什么普通的 HTTP 302 重新导向不好使? 这的确是一个事实。核心的问题是在服务端的脚本语言,而不是在服务端语言和服务器之间。 所谓的 302 Found HTTP 反应是指服务器告诉用户代理,它所需要的资源在另外的地方可以找到。302 反应可能包括一个人们可理解的信息,如果在这种情况下“ Content-type: ”就被设置了。笔者所测试 过的服务器,即使没有内容也都加了“Content-type:”。 默认的 “Content-type:” 是 text/html。当然 有些网关不喜欢这个类型。 以下的例子已经经过测试,在 Apache 和 Microsoft Internet Information Server 都可以工作。 如果 使用其他的 Web Server,或者其他的脚本语言,需要能转换这些简单的脚本。 关键的工作是十分简单的, 除非需要,不用告诉服务器整个 HTTP 头。 大多数 Web Server 将自动完成这个 HTTP 头,使得用户代理可以 理解。 所有的代码例子可以在线测试。 如果它们能够工作,用户将被重新引导到 http://wap.colorline.no/ clientinfo.html ,在那儿将产生一个 WML 页面来显示所有的 HTTP 头。 PHP 代码测试可以在 http://wap.colorline.no/wap-faq/apps/302test.php3 中找到。 <?     header("Location: http://wap.colorline.no/clientinfo.html");     header("Content-type: text/vnd.wap.wml"; ?>  Perl 测试代码可以在 http://wap.colorline.no/cgi-bin/302test.pl 中找到。  print "Location: http://wap.colorline.no/clientinfo.htmln"; print "Content-type: text/vnd.wap.wmln";  ASP 测试代码可以在 http://www.colorline.no/302test.asp 中找到。 (注意不同的 URL):  第 17 页 共 23 页
  • 18. <%     Response.Redirect = "http://wap.colorline.no/clientinfo.html";     Response.ContentType = "text/vnd.wap.wml";     Response.Flush     Response.End %> 43. 可能在 WML 中实现 ASP Session 吗? 不可能。 可以把信息存储在临时变量中模拟 Session。Session 是保存在用户 PC 上的“cookies”中。目 前的 WAP 设备不支持“cookies”。不过下一代的设备和 WML 可能支持“cookies”。 44. WAP 支持 Session 吗? 在 HTML 中,一个十分普遍的“处理”用户的方法就是为每个用户分配一个“session”。这个有时候 是通过指定一个独一无二的 cookies 来实现的。然而 WAP 的资源非常有限,因此 session 的处理必须以不 同的方式来处理。 Alex Kriegel 提供了一个安装在 WAPlinks 的 Custom Session Object 包。这个 zip 文件中包含了 VB 类的文件和编译过的 Dll 文件,还有相关的文档。这些可以在 http://www.waplinks.com/customsessionobject.zip 下载。 另外一种方法是使用 PHPlib ,它是使用 PHP 编写的。 Tarique (tarique@nagpur.dot.net.in) 提供了如何使用 PHPlib 来验证和处理每个 WAP 用户。 有相关 的文件和注释可以到下面地址下载: http://wap.colorline.no/wap-faq/archive/phplib_wml.zip 45. 可以在 WAP 中使用 Cookies 吗? 在理论上是可以的,但不是所有的 WAP 设备都支持。另一个方法来管理会话是使用隐藏的 fields(包 含会话标识,无论是 POST 或者 GET 方式)。 46. WAP 支持 Cookies 吗? 普通的 HTTP Cookies 是作为 WAP 的扩展来实现的。无论你以前听到什么,Cookies 的支持将越来越好。 实际上 Phone.com 的 UP.Link 网关已经支持这个功能有一段时间了。 可以使用以下的脚本语言检测 Cookie-support,: http://wap.colorline.no/wap-faq/apps/cookietest.php3 脚本在 http://wap.colorline.no/demos.html 也可以得到。 当第一次看见卡片的时候,记数器应该为 0。 所有的 Cache 都被关闭。 卡片通过在 URL 中随机地加入变 量来强制自己加载(笔者不推荐这种强制加载办法)。当点击增加计数连接,页面将重新加载,卡片就再 次出现,并且记数器变成 1。 在脚本中,Cookie 的名字被称做 TestCookie,它有很长的生命期,因此可以隔好几天再来查看记数 器,它将是上一次的数值。 这要求你能使用与上一次访问所使用的 WAP 环境一样,否则将把你的数值清 0。 如果记数装置一直都是 0,那么 cookie 就没有能传送到你的 Web Server。这个脚本也能表示 Cookie 是否被传送。 另外,这个脚本同样还显示 HTTP 头中的 HTTP_VIA 和 HTTP_USER_AGENT 。这些能够得到所使用的网 关和模式。一些网关使用 HTTP_VIS 标识自己,而另外一些使用 HTTP_USER_AGENT,还有一些则让程序无法 知道。 第 18 页 共 23 页
  • 19. 下面是它的 PHP 代码。 一个标准的 PHP setcookie() 函数只有在这种脚本语言中才会出现。函数只是 简单地设置 cookie,并且 PHP 变量 $HTTP_COOKIE_VARS 用来读取 cookie。 <? if(isset($HTTP_COOKIE_VARS["TestCookie"])) {// Check if TestCookie is set       $cookieset = "set"; // Read the Cookie       $cookieid = $HTTP_COOKIE_VARS["TestCookie"];   // and increase its value       $cookieid++;      }     else {   // cookie was not set       $cookieset = "not set";   // start counter at zero       $cookieid = 0;     }   // apply the Cookie to the HTTP header  setcookie("TestCookie",$cookieid);   // set the content type for WML     header("Content-type: text/vnd.wap.wml"); // disable ALL caching     header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");     header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");     header("Cache-Control: no-cache, must-revalidate");               header("Pragma: no-cache");     echo("<?xml version="1.0"?>n");  echo("<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"  "http://www.wapforum.org/DTD/wml_1.1.xml">nn");  echo("<!-- This application attempts to test the capabilities of a WAP gateway to support cookies -->n");     echo("<!-- App by Espen.Lyngaas@colorline.no (c) 2000 -->n");   // Generate random value for reload forcing     $random = mt_rand(100000,999999);  ?>   <wml>   <head> // Even more cache disabling <meta forua="true" http-equiv="Cache-Control" content="must-revalidate"/>    </head>   <card id="init" title="CookieTest">   <p>    Cookie "TestCookie" was <?echo($cookieset)?>.    Value is currently "<?echo($cookieid)?>" 第 19 页 共 23 页
  • 20.   </p>   <p> <anchor> Increase value <go method="get" href="<?echo($PHP_SELF)?>?random=<?echo($random)?>"/> </anchor> </p> <p>Gateway:    <?     if(isset($HTTP_VIA)) { // Is there something in the HTTP_VIA variable?       echo($HTTP_VIA);     }     else {       if(isset($HTTP_USER_AGENT)) { // Is there something in the HTTP_USER_AGENT variable?         echo($HTTP_USER_AGENT);       }       else { // Absolutely no identifier was found         echo("Unknown");       }     }   ?>   </p>   </card>   </wml> 47. 如何使用 WAP 设备发送 E-Mail? 在 HTML 中有一个默认的 E-Mail 机制:“ mailt” 。但在 WML 中不好使,因此 E-Mails 必须通过 WML 表单来解决。例如: <wml>      <card id="edit" title="Email Editor">       <p>From: <input type="text" name="from" format="*M"/></p>       <p>T <input type="text" name="to" format="*M"/></p>       <p>Subject: <input type="text" name="subject" format="*M"/></p>       <p>Message body: <input type="text" name="body" format="*M"/></p>       <p>         <anchor>Send this mail           <go method="post" href="http://some.host/mailhandler"?action=send/">             <postfield name="from" value="$(from)"/>             <postfield name="to" value="$(to)"/>             <postfield name="subject" value="$(subject)"/>             <postfield name="body" value="$(body)"/>           </go>        </anchor> 第 20 页 共 23 页
  • 21.       </p>    </card> </wml>  在代码中的 http://some.host/mailhandler 是一个 CGI 程序,它是服务端的脚本程序,将提交的表 单转换成 E-Mail 格式并发送出去。 如果想使用一个类似于发信的过程,就需要编辑变量名。另外发送的数据是有限的,长信息可能需要 打断。 为了演示它是如何工作的,下面的 PHP 脚本可以用来处理 Mail。它将格式化 WML 页面,告诉用户是 否发出信件。在真实的应用中,应该加入检测,例如:E-Mail 的合法格式。 <? // Tell the client that this is a WML deck     header("Content-type: text/vnd.wap.wml");     echo("<?xml version="1.0"?>n");     echo("<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">n"); // The name of your mail server     $mailer = "wap.colorline.no"; // Format the from field     $from = $from." (WAP user at ".$mailer.")"; // Add the from field and some character handling to the extra headers   $extraheaders = $from."nContent-Type: text/plain; charset=iso-8859-1nContent-Transfer-Encoding: 8bit"; // Start sending out the WML deck     echo("<wml>n");     if(mail($to,$subject,$body,$extraheaders)) {// Use PHP's internal mail functionality // Mail was successfully sent       echo("<card id="sent" title="Mail sent">n");       echo("<p>Mail was sent successfully</p>n");       echo("</card>n");     }     else { // The mail could not be sent       echo("<card id="notsent" title="Mail failed">n");        echo("<p>Unable to send mail</p>n");       echo("</card>n");     }     echo("</wml>n"); ?> 因为安全性的原因,以上的代码没有演示程序。 48. 可以在模拟器上操作本地的页面,却没有办法访问 Internet 上的,有什么问题吗? 第 21 页 共 23 页
  • 22. 大多数模拟器和工具都可以浏览 Internet、 Intranet 和本机的页面。 但是在访问一些大公司页面的时 候,必须通过代理服务器来取得进入 Internet 的权限。如果必须通过这个代理服务器来取得 HTML 页面, 那么你的 WAP 模拟器也会取得权限来访问 Internet。 注意到有些模拟器不支持代理服务器,但是大多数是支持的。在模拟器里面设置这些是很简单的。用 户所做的只需要将代理主机的名字、IP 地址和端口号输入就可以了。如果没有找到,你可以在 systems/network 管理器里面设置这些,也可以检查 Netscape/IE 的设置。 在某些情况下,代理服务器使用 userid 和 password 来取得进入 Internet 的权限。有些模拟器支 持用户代理服务器,用户应该能告诉模拟器相关的代理配置。 在极少的情况下,使用代理服务器(如 Microsoft Proxy Server,)的用户会遇到更多的问题。 这个 代理服务器只接受一种验证方式(userid/password)。这种验证被称做 NTLM ,并且是某种 MS 的验证 方式。几乎很少有模拟器支持这种方式。因此最好是避免使用它,或者让管理员使用“Basic Authentication”方式以避免更多的麻烦。 49. 什么是 PUSHing,它是如何工作的? PUSH 被加入到 WAP 1.2,而且只在 WAP 1.2 中才存在。简单地来说,PUSH 提供了另外一种从服务器向 用户发送数据的方式。PULLing 是从客户端请求信息,然后接收它;PUSH 意味着服务器可以向用户发送数 据,而不需要用户来请求。 内容或者应用服务器无法向用户代理直接发送数据,必须使用一种叫做 Push Proxy 的网关。PPG 是 基于 Internet 的 Push Initiator (内容或者应用服务器) 与移动用户之间的。在 Internet 一边,使用 Push Access Protocol,在移动网络一边使用 Push Over-the-Air Protocol。 当前只有 WAP 1.2 开发平台支持 PUSH, 例如 Nokia Toolkit 2.0。 Nokia Toolkit 2.0 only 内 部支持 PUSHing,意味着用户可以从工具包的界面将消息推送到模拟器。如果想试着到一个外部的 Push Proxy Gateway, 工具包就崩溃了。从 readme 文件中知道,PUSHing 还没有经过完整的测试。 50. WAP 模拟器说 text/html 不支持,但是用户的 MIME 设置是正确的,为什么? 当使用服务端的脚本语言,例如 ASP、PHP 或者 Perl,来生成 WML 输出,或者从 HTTP 服务器提供 WML 页面的时候。记住 HTTP 一般默认的显示是 HTML,其 MIME 类型是 text/html。 如果 HTTP 服务器或者服务器脚本有错误,错误的信息将使用 HTML 显示,因此微型浏览器是不能显示 错误信息的。 一个开发工具/模拟器可以让用户看到从 HTTP 服务器过来的代码。 例如,在 Nokia SDK 中,这个功能 被称做 View Source。通过看代码可以知道 HTTP 服务器到底发送了些什么内容。也可以使用普通的浏览器 来查看任何 HTML 格式的错误信息。 51. 在哪儿有 Visio 移动电话的模板库? 目前唯一知道的就是它包含在 Nokia 7110 中。 52. 有没有其他有用的 WML 内容服务列表? 这里至少有一个。 对于 Unix 用户, http://pwot.co.uk/wml/中有 Thomas Neill (ponder@pwot.co.uk)提供的 WML 工具,包括 WML 二进制编译和反编译。 Angus 和 Zygo WAP(angus@z-y-g-o.com)已经开发出了一个 Perl 工具包。 它还在为管道式的 WML 编 译器工作。 53. XML 到 XSL 的转换可以应用到 WML 和 WAP 吗? 第 22 页 共 23 页
  • 23. 既然 WML 实际上是 XML,并且 XSL 将 WML 转换成其他不同的 XML 文档,那么问题的答案是显然的:XSL 也可以应用到 WML。可以参考 Luca Passani 的文章《WebTechniques 。这个文章在网络上的地址是 : 》 http://www.webtechniques.com/archives/2000/03/passani/ 它推荐看一下叫做 《在 Apache 下 Cocoon 计划的实现》这篇文章。 “Cocoon 是一个依赖于新的 W3C 技 术(例如 DOM,XML,和 XSL)框架。 Cocoon 计划在于改变 Wen 信息创建,生成和提供的方式。 文档内容、 风 格和逻辑经常因为个人或者工作组的不同而不同。 Cocoon 目标在于将这三层分离,允许三层次之间进行 独立的设计,创建和管理,减少相互之间的影响,增加工作的可复用性以及缩短上市的时间。Web 内容的 产生大多数是基于 HTML 的,但是 HTML 并不能将三者分离开来,混合着各种格式标签,程序逻辑等等。而 Cocoon 计划将要改变这种情况,允许内容,逻辑和风格相互分离。使用 XML 来保存,但是使用 XSL 来将它 们混合。” 基本上来说,Cocoon 将解读 HTTP 头,判断使用的是什么浏览器,然后使用不同的风格来选择正确的 页面,使用 XSL 进行混合。 54. 想让用户只要简单地按下一个按钮就能够转跳到其他卡片而不是通过选择 URL,这个可能吗? 不,不可能。 55. 如何避免一个行的中断以便可以在一行中输入多个链接? 在 Nokia 7110 中,不可能做到这一点,每个链接都占据自己的一行。 第 23 页 共 23 页