Friday, September 2, 2011

使用 ob_start()来缓存输出


假设要设置cookie或者有html提前输出,但是会导致后面的页面跳转(header()函数
)出现错误。在跳转直接不允许有输出。所以可以在输出的html内容的最前面使用ob_start()来缓存输出,然后在跳转等的函数结束后,使用ob_end_flush()把缓存的内容输出到浏览器上
例如
Ob_start();
session_start();
    $session_id = session_id();
    $_SESSION[$session_id] = $username;
setcookie('website',$session_id,time()+60);
echo "登录成功!!<a href="."\"auth.php\">登录</a>";
    echo "<script>alert('登录成功');</script>";
    echo "<script>window.location.href='"."auth.php';</script>";
    echo "<script>setTimeout('alert("."111)',2000);</script>";
header("refresh:3,url=auth.php");
    ob_end_flush();

Drupal7.7的测试,css框架调整



CSS框架中padding的用法
   今天在linux环境下重新搭建了drupal-7.7的版本,确实觉得相当的不错。首先用linux的服务器性能比windows明显有很大优势,然后就是本身drupal的特色决定,自从7的版本以后变得很稳定,唯独一个小问题,就是文件上传的时候,如果是中文名的文件是总会出错,默认会把文件名改掉,但是这样就不符合drupal的上传文件类型了,所以很无语。。。。
      看了网上一些办法是把file.inc里面的一个函数给改掉,也没有弄太懂,不过总觉得解决这个问题要改动源代码的话总是一个危险的操作。后来也有人说一个模块translations的貌似,可以将所以的中文文件名自动转换为拼音,猛然想来这个注意不错,后来一想,万一文件名很长,而且又抽象,例如wojiushiyigezhongwenmingziwenjian.txt。。。天啊,那可是看着就晕了。。。。不过现在还没有什么好的解决办法,先晾着吧
        说说主要的心得,今天下了好几个不同的主题,安装上界面效果感觉就是不一样,很漂亮。现在我测试用的是corporateclean的主题,有slide show的首页效果,我一直很喜欢这种感觉,滑动感很强,后来发现没有快速的修改其中的图片,这个让我很郁闷阿,难不成增删操作要真的去修改源代码来添加图片吗?经过测试。。。不幸言中了。
在该主题目录下面有page.tpl.php,这个是一个模板文件,slide图片的css设计就在这个其中定义。然后找到
  <!--slideshow-->
    <div id="slideshow">
  这个就是开始定义
   
以下的都是每一幅图片对应的参数
        <!--slider-item-->
        <div class="slider-item">
            <div class="content">
               
                <!--slider-item content-->
                <div style="float:left; padding:0 30px 0 0;">   这个是图片的样式定义
                <img height="250px" class="masked" src="<?php print base_path() . drupal_get_path('theme', 'corporateclean') ;?>/mockup/slide-1.jpg"/>
                </div>
                <h2>Sample product name</h2>
                <strong>General</strong><br/>
                <em>Client name</em><br/>
                <br/>
                Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
                <div style="display:block; padding:30px 0 10px 0;"><a class="more" href="#">Tell me more</a></div>
                <!--EOF:slider-item content-->
               
            </div>
        </div>
        <!--EOF:slider-item-->
       
       
        从上述的代码中,就可以设置图片的引用,并且在该文件中,复制粘贴如上的代码,就可以增加主页上的图片slide。
        记得在最后一点
        <!--slider-controls-wrapper-->
    <div id="slider-controls-wrapper">
        <div id="slider-controls">
            <ul id="slider-navigation">
                <li><a href="#"></a></li>
                <li><a href="#"></a></li>
                <li><a href="#"></a></li>
                <li><a href="#"></a></li>
                <li><a href="#"></a></li>
                <li><a href="#"></a></li>
            </ul>
        </div>
    </div>
   
    这样的代码,有几个图片,就要有多少"<li><a href="#"></a></li>"
   
    然后是padding的用法,<div style="float:left; padding:0 30px 0 0;">,其中float有几种样式,left\right\bottom\top,每个方式代表在在框架中的哪个位置,padding:参数按照上、右、下、左的顺序设置补的距离
   
    如简写方式有:
padding:10px; 意思就是上下左右补丁距离就是10px(10像素)
padding:5px 10px; 意思上下补丁距离为5px,左右的补丁距离为10px,
padding:5px 6px 7px; 意思上补丁距离5px,下补丁距离为7PX,左右补丁距离为6px,
padding:5px 6px 7px 8px; 意思上补丁为5px,右补丁距离为6px ,下补丁距离为7px,左补丁距离8px

如果想要图片向右一些,可以设置第四个参数变大,就可以将内容向右移动

win7备份wubi安装的Ubuntu


win7备份ubuntu
复制ubuntu\winboot\下的wubildr   wubildr.cfg    wubildr.mbr三个文件到win7系统盘根目录

使用命令行,输入
bcdedit /create /d "Ubuntu" /application bootsector
此时系统会自动生成一个{id}   注意:id为{}类的一串数字和字母,以下id应填写为该字符串

bcdedit /set {id} device partition=f:      (f为wubi安转的ubuntu的盘符)

bcdedit /set {id} path \ubuntu\winboot\wubildr.mbr  这个是引导文件的路径

bcdedit /displayorder {id} /addlast



网上的一个版本
一、重装xp后恢复Ubuntu启动项(用wubi安装的Ubuntu)
    我把安装ubuntu->winboot文件夹下wubidr和wubidr.mbr两个文件拷到C盘根目录下,然后用记事本打开c盘下的boot.ini,在最后一行加入c:\wubildr.mbr="Ubuntu"就可以了,然后保存重启。我想要的ubuntu启动项出来了!!!
    二、Vista或windows7下恢复Ubuntu启动项(用wubi安装的Ubuntu)
    最近重装了Windows7(vista同理),不想却让之前装的Ubuntu没有启动项了,Windows7(vista同理)没有boot.ini文件编辑的方法,由于当时Ubuntu是用wubi在Windows下安装的!
    恢复方法:
    1.把安装ubuntu->winboot文件夹下wubidr和wubidr.mbr两个文件拷到C盘根目录下
    2.在“运行”中输入cmd到命令提示
    在命令界面bcdedit /create /d "linux" /application bootsector
    得到像c:\windows\system32>bcdedit /create /d "Ubuntu" /application bootsector
    //多启动菜单上显示的名字项 {dbff544b-a7c4-11dd-a51d-00155803ebb4} 成功创建。
    3.把{}中的id复制下来,如:dbff544b-a7c4-11dd-a51d-00155803ebb4
    4.再输入下列命令  (注意:自己替换下面{}中的id为第2步得到的id)
    bcdedit /set {id} device partition=c:
    bcdedit /set {id} path \wubildr.mbr
    bcdedit /set {id} description "Ubuntu"
    bcdedit /displayorder {id} /addlast

数据库小学期中Sybase与PHP的连接配置教程


(本人是使用的PHP脚本语言,配合apache服务器操作,如果大家用jsp或者asp,.net等,或者不用apache,就可以基本忽略如下详细内容。。。。。。)
       昨天花了大半天时间去实验如何让PHP调用sybase的接口操作数据库,Sybase真是够恶心的,我和“大师”先后试了用扩展模块的方式(无法被appche服务器加载)、ODBC方式(连上了,但是操作不了,增删改查都有问题),ADO方式(也是不好用,对象集有点复杂)。一般连接数据库只有这三个方式,最简单的当属用扩展模块的方式,这样php中自定义的的有sybase的函数,只需要sybase的模块被php和apache挂载即可。那么如何操作见下文:
   1、安装Sybase(废话),当然最好的是选择全部安装,使用开发者版本,这样就可以一直免费了。因为老师上学期给过的是15.0的版本,我个人觉得那个看起来有点别扭,自己又去官网下了15.5最新版,现在已经放到大班网站上了,地址:http://buptwg.com/index.php?q=node/89,这个版本最大的好处是:全部中文。
  2、连接web的时候是需要sybase的一个open client的组件,所以第一条要全部安装。
  3、安装后,找到sybase的安装目录,例如CK_Sybase/,然后,进入CK_Sybase/OCS-15.0/dll/,里面有很多dll文件,找到  libsybct.dll 和libsybcs.dll , 将这两个文件复制,粘贴到本目录下,修改名字, libsybct.dll------>libct.dll
libsybcs.dll----->libcs.dll。
  4、然后找到php的配置文件,php.ini,如果大家用的wamp一键安装服务器的话,在开启之后,电脑右下角的图标左键单击,然后里面寻找php,就有php.ini配置文件了;当然如果是自己开发过web,分开安装的apache和php,那么一般都在c:\windows目录下。  
   5、找到之后,搜索  ;extension=php_sybase_ct.dll ,此刻注意前面有一个分好,代表是该扩展模块未加载。将分号去掉。保存退出。
6、重启apache服务器,应该都会吧
7、为了检测sybase的模块是否被php成功加载了,在web根目录下面写一个php文件,命名为phpinfo.php,用编辑器打开后,写入
<?php
phpinfo();
?>
保存退出。
8、访问该文件,查找是否有sybase_ct的模块。如果有,就恭喜你加载成功!
当然后面就是啰嗦两句废话啦,翻找php手册,自己查询相关的调用数据库的函数吧~
比如连接是 sybase_connect('服务名','用户名','密码',‘字符集’),这个是大师发现的,牛叉!因为sybase的字符集非常诡异,CP936的,所以不指定字符集连接的话,查到的结果有中文的话显示到浏览器中都是乱码了。
选择数据库是 sybase_select_db(连接名,‘数据库名’)
执行是 sybase_query()
需要注意的是,sybase的这个模块做的不是很好,所以调用这些函数时会出现警告,但是是可以使用的,所以在函数前面加上@,屏蔽警告,比如@sybase_query()。

剩下的就靠大家各自发挥了啊~

Wednesday, August 24, 2011

实现自己的http server(转)

Write your own http server
author : Kevin Lynx
Why write your own?
    看这个问题的人证明你知道什么是http server,世界上有很多各种规模的http server,为什么要自己实现一个?其实没什么
理由。我自己问自己,感觉就是在自己娱乐自己,或者说只是练习下网络编程,或者是因为某日我看到某个库宣称自己附带一个小
型的http server时,我不知道是什么东西,于是就想自己去实现一个。
What's httpd ?
    httpd就是http daemon,这个是类unix系统上的名称,也就是http server。httpd遵循HTTP协议,响应HTTP客户端的request,
然后返回response。
    那么,什么是HTTP协议?最简单的例子,就是你的浏览器与网页服务器之间使用的应用层协议。虽然官方文档说HTTP协议可以
建立在任何可靠传输的协议之上,但是就我们所见到的,HTTP还是建立在TCP之上的。
    httpd最简单的response是返回静态的HTML页面。在这里我们的目标也只是一个响应静态网页的httpd而已(也许你愿意加入CGI
特性)。
More details about HTTP protocol
    在这里有必要讲解HTTP协议的更多细节,因为我们的httpd就是要去解析这个协议。
    关于HTTP协议的详细文档,可以参看rfc2616。但事实上对于实现一个简单的响应静态网页的httpd来说,完全没必要读这么一
分冗长的文档。在这里我推荐<HTTP Made Really Easy>,以下内容基本取自于本文档。
- HTTP协议结构
  HTTP协议无论是请求报文(request message)还是回应报文(response message)都分为四部分:
  * 报文头 (initial line )
  * 0个或多个header line
  * 空行(作为header lines的结束)
  * 可选body
  HTTP协议是基于行的协议,每一行以作为分隔符。报文头通常表明报文的类型(例如请求类型),报文头只占一行;header line
  附带一些特殊信息,每一个header line占一行,其格式为name:value,即以分号作为分隔;空行也就是一个;可选body通常
  包含数据,例如服务器返回的某个静态HTML文件的内容。举个例子,以下是一个很常见的请求报文,你可以截获浏览器发送的数据
  包而获得:
    1  GET /index.html HTTP/1.1
    2  Accept-Language: zh-cn
    3  Accept-Encoding: gzip, deflate
    4  User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; MAXTHON 2.0)
    5  Host: localhost
    6  Connection: Keep-Alive
    7
  我为每一行都添加了行号,第1行就是initial line,2-6行是header lines,7行是一个header line的结束符,没有显示出来。
  以下是一个回应报文:
    1  HTTP/1.1 200 OK
    2  Server: klhttpd/0.1.0
    3  Content-Type: text/html
    4  Content-Length: 67
    5
    6  <head><head><title>index.html</title></head><body>index.html</body>
  第6行就是可选的body,这里是index.html这个文件的内容。
- HTTP request method
  因为我们做的事服务器端,所以我们重点对请求报文做说明。首先看initial line,该行包含几个字段,每个字段用空格分开,例
  如以上的GET /index.html HTTP/1.1就可以分为三部分:GET、/index.html、HTTP/1.1。其中第一个字段GET就是所谓的request
  method。它表明请求类型,HTTP有很多method,例如:GET、POST、HEAD等。
  就我们的目标而言,我们只需要实现对GET和HEAD做响应即可。
  GET是最普遍的method,表示请求一个资源。什么是资源?诸如HTML网页、图片、声音文件等都是资源。顺便提一句,HTTP协议
  中为每一个资源设置一个唯一的标识符,就是所谓的URI(更宽泛的URL)。
  HEAD与GET一样,不过它不请求资源内容,而是请求资源信息,例如文件长度等信息。
- More detail 
  继续说说initial line后面的内容:
  对应于GET和HEAD两个method,紧接着的字段就是资源名,其实从这里可以看出,也就是文件名(相对于你服务器的资源目录),例
  如这里的/index.html;最后一个字段表明HTTP协议版本号。目前我们只需要支持HTTP1.1和1.0,没有多大的技术差别。
  然后是header line。我们并不需要关注每一个header line。我只罗列有用的header line :
  - Host : 对于HTTP1.1而言,请求报文中必须包含此header,如果没有包含,服务器需要返回bad request错误信息。
  - Date : 用于回应报文,用于客户端缓存数据用。
  - Content-Type : 用于回应报文,表示回应资源的文件类型,以MIME形式给出。什么是MIME?它们都有自己的格式,例如:
    text/html, image/jpg, image/gif等。
  - Content-Length : 用于回应报文,表示回应资源的文件长度。
body域很简单,你只需要将一个文件全部读入内存,然后附加到回应报文段后发送即可,即使是二进制数据。
- 回应报文
  之前提到的一个回应报文例子很典型,我们以其为例讲解。首先是initial line,第一个字段表明HTTP协议版本,可以直接以请求
  报文为准(即请求报文版本是多少这里就是多少);第二个字段是一个status code,也就是回应状态,相当于请求结果,请求结果
  被HTTP官方事先定义,例如200表示成功、404表示资源不存在等;最后一个字段为status code的可读字符串,你随便给吧。
  回应报文中最好跟上Content-Type、Content-Length等header。
具体实现
    正式写代码之前我希望你能明白HTTP协议的这种请求/回应模式,即客户端发出一个请求,然后服务器端回应该请求。然后继续
这个过程(HTTP1.1是长连接模式,而HTTP1.0是短连接,当服务器端返回第一个请求时,连接就断开了)。
    这里,我们无论客户端,例如浏览器,发出什么样的请求,请求什么资源,我们都回应相同的数据:

C++代码
  1. /**//* 阻塞地接受一个客户端连接 */  
  2.         SOCKET con = accept( s, 0, 0 );    
  3.         /**//* recv request */  
  4.         char request[1024] = { 0 };   
  5.         ret = recv( con, request, sizeof( request ), 0 );   
  6.         printf( request );   
  7.         /**//* whatever we recv, we send 200 response */  
  8.         {   
  9.             char content[] = "<head><head><title>index.html</title></head><body>index.html</body>";   
  10.             char response[512];   
  11.             sprintf( response, "HTTP/1.1 200 OKContent-Type: text/htmlContent-Length: %d%s", strlen( content ), content );   
  12.             ret = send( con, response, strlen( response ), 0 );   
  13.         }   
  14.         closesocket( con );   

程序以最简单的阻塞模式运行,我们可以将重点放在协议的分析上。运行程序,在浏览器里输入http://localhost:8080/index.html
,然后就可以看到浏览器正常显示content中描述的HTML文件。假设程序在8080端口监听。
   现在你基本上明白了整个工作过程,我们可以把代码写得更全面一点,例如根据GET的URI来载入对应的文件然后回应给客户端。
其实这个很简单,只需要从initial line里解析出(很一般的字符串解析)URI字段,然后载入对应的文件即可。例如以下函数:

C++代码
  1. void http_response( SOCKET con, const char *request )   
  2. {   
  3.     /**//* get the method */  
  4.     char *token = strtok( request, " " );   
  5.     char *uri = strtok( 0, " " );   
  6.     char file[64];   
  7.     sprintf( file, ".%s", uri );    
  8.   
  9.     {   
  10.         /**//* load the file content */  
  11.         FILE *fp = fopen( file, "rb" );   
  12.         if( fp == 0 )   
  13.         {   
  14.             /**//* response 404 status code */  
  15.             char response[] = "HTTP/1.1 404 NOT FOUND";   
  16.             send( con, response, strlen( response ), 0 );   
  17.         }   
  18.         else  
  19.         {   
  20.             /**//* response the resource */  
  21.             /**//* first, load the file */  
  22.             int file_size ;   
  23.             char *content;   
  24.             char response[1024];   
  25.             fseek( fp, 0, SEEK_END );   
  26.             file_size = ftell( fp );   
  27.             fseek( fp, 0, SEEK_SET );   
  28.             content = (char*)malloc( file_size + 1 );   
  29.             fread( content, file_size, 1, fp );   
  30.             content[file_size] = 0;    
  31.   
  32.             sprintf( response, "HTTP/1.1 200 OKContent-Type: text/htmlContent-Length: %d%s", file_size, content );   
  33.             send( con, response, strlen( response ), 0 );   
  34.             free( content );   
  35.         }   
  36.     }   
  37. }    
  38.   

其他
    要将这个简易的httpd做完善,我们还需要注意很多细节。包括:对不支持的method返回501错误;对于HTTP1.1要求有Host这个
header;为了支持客户端cache,需要添加Date header;支持HEAD请求等。
    相关下载中我提供了一个完整的httpd library,纯C的代码,在其上加上一层资源载入即可实现一个简单的httpd。在这里我将
对代码做简要的说明:
    evbuffer.h/buffer.c : 取自libevent的buffer,用于缓存数据;
    klhttp-internal.h/klhttp-internal.c :主要用于处理/解析HTTP请求,以及创建回应报文;
    klhttp-netbase.h/klhttp-netbase.c :对socket api的一个简要封装,使用select模型;
    klhttp.h/klhttp.c :库的最上层,应用层主要与该层交互,这一层主要集合internal和netbase。
    test_klhttp.c :一个测试例子。
相关下载:
    klhttpd
    文中相关代码
参考资料: