Linux+apache+mysql 搭建一个基于CGI的留言系统练习

系统概要: 

 1 系统一共有两个页面包括登录页面login.html和msg.html,showmsg.html
 2  系统用户在login页面输入用户名和密码登录系统,登录成功后自动跳转到msg.html页面进行留言
 3 在msg.html页面留言填入相关留言后点击提交
 4  系统管理员登录后转到showmsg.html可以分页查看所有的留言信息。   
          

 二  数据库设计与实现

  建立表user (id,name,password,role)
   msg(title,content,submitTime)
在PowerDesigner中设计好表与表之间的关系得到  建立数据库的SQL语句如下:
/*==============================================================*/
/* DBMS name:      MySQL 4.0                                    */
/* Created on:     2010-6-29 11:51:14                           */
/*==============================================================*/


drop index Relationship_1_FK on Msg;
drop table if exists Msg;
drop table if exists User;
/*==============================================================*/
/* Table: Msg                                                   */
/*==============================================================*/
create table Msg
(
   MsgID                          decimal                        not null AUTO_INCREMENT,
   UserID                         decimal                        not null,
   Title                          varchar(50)                    not null,
   Content                        text                           not null,
   SubmitTime                     datetime                       not null,
   primary key (MsgID)
)
type = InnoDB;
/*==============================================================*/
/* Index: Relationship_1_FK                                     */
/*==============================================================*/
create index Relationship_1_FK on Msg
(
   UserID
);
/*==============================================================*/
/* Table: User                                                  */
/*==============================================================*/
create table User
(
   UserID                         decimal                        not null AUTO_INCREMENT,
   Name                           varchar(50)                    not null,
   Password                       varchar(15)                    not null,
   Role                           varchar(50)                    not null,
   primary key (UserID)
)
type = InnoDB;
alter table Msg add constraint FK_UserHaveMsg foreign key (UserID)
 references User (UserID) on delete restrict on update restrict;
 

添加唯一约束的语句:
alter table User add constraint uq_name UNIQUE(Name);
 
注意的地方
编译C程序时的编译选项
gcc  -I/usr/local/mysql/include mysqltest.c -o mysample  -L/usr/local/mysql/lib -lmysqlclient -IZ
 
编译C++程序时的编译选项
g++  -I/usr/local/mysql/include mytest.cpp -o mysample  -L/usr/local/mysql/lib -lmysqlclient -lz
(在加入了 -lz选项后总出现 cannot find -lz的错误 刚开始的时候以为是装mysql的时候装错了原来是装操作系统的时候少装zlib库,直接导致耽误了2个小时的时间)
 
三 C++ 连接MYSQL数据库后的CRUD操作的封装:
连接数据库用到的API :
mysql_init(&mysql)
mysql_real_connect(&mysql,_host,_user,_passwd,_db,0,NULL,0)
mysql_real_query(&mysql,chSql,strlen(chSql))==0
MYSQL_RES   *rs   =   NULL; 
        if(ExecuteSql(   chSql   )) 
        { 
                rs   =   mysql_store_result(&mysql); 
        } 
        return   rs; 
 mysql_free_result(result); 
 mysql_close(&mysql); 
 
 
查询结果的处理
MYSQL_RES *result;
unsigned int num_fields;
unsigned int num_rows;

if (mysql_query(&mysql,query_string))
{
    // error
}
else // query succeeded, process any data returned by it
{
    result = mysql_store_result(&mysql);
    if (result)  // there are rows
    {
        num_fields = mysql_num_fields(result);
        // retrieve rows, then call mysql_free_result(result)
    }
    else  // mysql_store_result() returned nothing; should it have?
    {
        if (mysql_errno(&mysql))
        {
           fprintf(stderr, "Error: %s\n", mysql_error(&mysql));
        }
        else if (mysql_field_count(&mysql) == 0)
        {
            // query does not return data
            // (it was not a SELECT)
            num_rows = mysql_affected_rows(&mysql);
        }
    }
}
编译源程序的语句
  g++  -I/usr/local/mysql/include msg.cpp DBmysql.cpp MsgEntity.cpp UserEntity.cpp -o mysample  -L/usr/local/mysql/lib -lmysqlclient -lz
 
该端口映射的方法
  
/usr/sbin/iptables -F;
/usr/sbin/iptables -I INPUT -p tcp -i eth0 --dport 80 -j ACCEPT; 
/usr/sbin/iptables -A INPUT -i eth0 -p tcp -j DROP;
/usr/sbin/iptables -A INPUT -i eth0 -p udp -j DROP;
运行这些命令就可以访问80端口了
CGI读取前台表单的数据:
C语言的只能识别具有name 属性的 表单元素
由表单生成的"名/值"对用"&"符号隔开,空格变成加号"+"号,有些字符以16进制表示成"%××"。
 
四。 业务逻辑的实现
 
通过CGI处理前台的页面请求的原理是:
1 前台表单页面在设置form标签的action属性时指定 相应的后台cgi的地址 例如<form action="http://localhost/cgi-bin/mysample" method="POST"  name="msgform" >     这个CGI的地址是可以在apache的配置文件中修改相应的在服务器的映射地址的,我在本地机上httpd.conf文件中设置为:ScriptAlias /cgi-bin/ "/mnt/hgfs/PC share/project/msg/"  这样的话就达到了映射的目的
2  在前台表单中提交触发变得提交事件 document.msgform.submit();   通过javascript实现 ,然后浏览器把表单数据进行编码后直接发送到apache服务器,apache根据表单书所请求的cgi,把该请求转叫给CGI程序处理,  CGI的C程序可以通过在环境变量中读取该数据后进行处理。 在前台设置标签属性是要设定name属性,这样的话才能在后台读取,设置id的在后台读取时会出错
C语言的只能识别具有name 属性的 表单元素
由表单生成的"名/值"对用"&"符号隔开,空格变成加号"+"号,有些字符以16进制表示成"%××"。
所以未来联系还要再写一个字符串分离的函数,实现 把name和value分开,存于map结构中,用以方便实现后台逻辑
 
五。总结
   1 通过写CGI来实现相关的业务逻辑,可以说对于整个后台架构来说,要求比较高,并且相当的灵活,而且具有很高的执行效率,而且我还没发现怎么来实现在CGI后台来托管用户登录的Session机制, 歪歪想了一下,可以通过写入一个唯一的数据库或文件来实现session机制。
   2 在设置apache的时候要主要文件权限的设置。
  3 对于C++的整个工程结构, 我还是按照了写C#的习惯, 一个表就有一个实体类对应起来,并且把相关的CRUD方法封装为静态方法。  感觉在设计整个业务系统时面向对象的设计方式并没有体现出来,工程文件结构有待学习。 
posted @ 2010-07-02 20:03  smile2you  阅读(743)  评论(0编辑  收藏  举报