入门教程_android studio入门教程 - CSDN
精华内容
参与话题
  • Halcon 入门教程(01)

    万次阅读 2019-05-11 15:41:34
    Halcon 入门教程(01) 这篇教程很简单,实现的功能是计算下图中曲别针的数量和每个曲别针的朝向。主要内容是翻译自Halcon 的帮助文档 “Chapter 4 Programming HDevelop”。 使用的图像如下: 这篇教程中我们假设 ...

    Halcon 入门教程(01)

    这篇教程很简单,实现的功能是计算下图中曲别针的数量和每个曲别针的朝向。主要内容是翻译自Halcon 的帮助文档 “Chapter 4 Programming HDevelop”。

    使用的图像如下:
    在这里插入图片描述这篇教程中我们假设 HDevelop 的各个参数都为默认值,通常新安装好的 HDevelop 所有的参数就都是默认值。如果不是的话可以通过下面的命令行方式将 HDevelop 的各个参数重置为默认值。

    hdevelop -reset_preferences

    首先打开 HDevelop ,如果我们调整过各个窗口的位置,则可以通过菜单命令 Window ⇒ Organize Windows 将各个窗口恢复原始位置。

    加载图像

    加载图像有多重方式,最简单的方式是把图像拖拽到 HDevelop 中。这时会自动弹出一个 Read Image 窗口,在这个窗口中可以设置一些基本的参数。
    在这里插入图片描述加载完成后会在 Program window 中显示对应的语句。当然我们也可以直接在这个窗口中输入这个语句。或者在 Operator Window 中输入 read_image,这时这个窗口会提供这个函数的功能解释,在这个 window 中还可以设置每个输入输出参数。

    读取完图像后的第二个操作是阈值分割 threshold。同样在 Operator Window 中输入 threshold。按照下图设置参数,之后点击 apply 按钮。这时会直接执行这条语句,但是不会把这条语句加入到 Program Window 中。我们可以试着调整参数,通过 apply 按钮,直接获得当前参数的效果。在 graphics window 中可以很直观的看到结果,红色的区域就是通过 Threshold 选出的区域。确认参数之后点击 OK 按钮将该命令加入到 Program Window 中。

    下一步操作是获取连通区域。 Halcon 有个非常好的功能就是可以给出建议的操作。菜单 Suggestions ⇒ Successors 会提示出 Threshold 之后经常跟着的命令。可以看到第一个就是 connection。执行 connection 的结果是获得各个连通区域。graphics window 中会用不同的颜色显示不同的连通区域。
    在这里插入图片描述
    Graphics window 有许多参数可以设置,在这个窗口上单击邮件,弹出的对话框如下图所示。
    在这里插入图片描述点击 Set Parameters 后打开如下对话框:
    在这里插入图片描述
    大家可以随便试试,各个参数的含义都比较简单。

    鼠标放在 ConnectedRegions 变量上单击鼠标右键后会弹出如下的菜单。
    在这里插入图片描述
    点击 Select 可以看到每个 Region 的详细信息,总共有 98 个区域。
    在这里插入图片描述
    实际上我们没有这么多的曲别针,产生这么多的区域说明我们的 threshold 的参数不合适。下面就来研究如何能进一步优化 Threshold 参数。

    菜单 Visualization/Tools → Gray Histogram 会打开 Gray Histogram 窗口。我们调整 threshold 时选中的区域会跟着变化。
    在这里插入图片描述通过这个 Gray Histogram 可以比较容易的选择合适的 Threshold。

    调整 Threshold 参数后得到的区域少了很多,但是还是比曲别针的数量多。这就说明我们需要其他的方法了。 Halcon 提供了一个 Feature Histogram 功能,这个功能除了通过 Histogram 来划分区域还会使用 Region 的其他 Feature。对于我们这个 区别的需求来说,面积就是一个非常好用Feature,因为所有的曲别针都有几乎相同的面积。下面我们就来具体的操作。

    菜单 Visualization/Tools → Feature Histogram 可以打开 Feature Histogram 窗口。按照下图中的参数设置就好。需要注意的是我用红色框框起来的区域。这块如果不是打勾状态,则 Insert Code 按钮就无法点击。
    在这里插入图片描述点击 Insert Code 后就会生成实际的代码:

    select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 6302.75, 8541.28)
    

    我们还要计算每个曲别针的方向,这可以用下面这条语句:

    orientation_region (SelectedRegions, Phi)
    

    然后这条语句计算每个区域的面积和中心点坐标。

    area_center (SelectedRegions, Area, Row, Column)
    

    最后我们要把结果显示在屏幕上。首先在整个程序之前增加一条语句:

    dev_close_window ()
    

    这条语句的作用是关闭任何已经打开的图像窗口。再加一句:

    dev_open_window (0, 0, 512, 512, ‘black’, WindowHandle)

    这条语句新建一个窗口。我们后面可以通过 WindowHandle 来操作这个窗口。

    下面是显示每一个曲别针的方向:

    dev_disp_text (deg(Phi) + ' degrees', 'image', Row, Column, 'black', [], [])
    

    输出的结果如下:
    在这里插入图片描述

    展开全文
  • Hive教程(一) Hive入门教程

    万次阅读 多人点赞 2017-10-10 22:25:51
    Hive是基于Hadoop的一个数据仓库工具,...Hive是一个数据仓库基础工具在Hadoop中用来处理结构化数据。它架构在Hadoop之上,总归为大数据,并使得查询和分析方便。 在Hive中,Hive是SQL解析引擎,它将SQL语句转译成M/R

     

     

    Hive教程() Hive入门教程

     

    1 Hive入门教程

    Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供简单的sql查询功能,可以将sql语句转换为MapReduce任务进行运行。其优点是学习成本低,可以通过类SQL语句快速实现简单的MapReduce统计,不必开发专门的MapReduce应用,十分适合数据仓库的统计分析。Hive是一个数据仓库基础工具在Hadoop中用来处理结构化数据。它架构在Hadoop之上,总归为大数据,并使得查询和分析方便。

    Hive中,HiveSQL解析引擎,它将SQL语句转译成M/R Job然后在Hadoop执行。Hive的表其实就是HDFS的目录/文件,按表名把文件夹分开。如果是分区表,则分区值是子文件夹,可以直接在M/RJob里使用这些数据。

    最初,Hive是由Facebook开发,后来由Apache软件基金会开发,并作为进一步将它作为名义下ApacheHive为一个开源项目。它用在好多不同的公司。例如,亚马逊使用它在Amazon ElasticMapReduce 

    1.1 Hive原理图


    1-1 Hive系统架构图

    1.2 Hive系统架构

    Hive系统架构图:

    1、用户接口:

    CLI,即Shell命令行。

    JDBC/ODBC HiveJava,与使用传统数据库JDBC的方式类似。

    WebGUI是通过浏览器访问 Hive

    2、Thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++,Java, Go,Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript,Node.js, Smalltalk, and OCaml这些编程语言间无缝结合的、高效的服务。

    3、解释器、编译器、优化器完成HQL查询语句从词法分析、语法分析、编译、优化以及查询计划(plan)的生成。生成的查询计划存储在HDFS中,并在随后有MapReduce调用执行。

    4、Hive的数据存储在 HDFS中,大部分的查询由 MapReduce完成(包含 * 的查询,比如 select *from table不会生成 MapRedcue任务)。

    5、Hive将元数据存储在数据库中(metastore),目前只支持mysqlderbyHive中的元数据包括表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等。

     

    Metastore组件:

    HiveMetastore组件是Hive元数据集中存放地。Metastore组件包括两个部分:Metastore服务和后台数据的存储。后台数据存储的介质就是关系数据库,例如Hive默认的嵌入式磁盘数据库derby,还有mysql数据库。Metastore服务是建立在后台数据存储介质之上,并且可以和Hive服务进行交互的服务组件,默认情况下,Metastore服务和Hive服务是安装在一起的,运行在同一个进程当中。我也可以把Metastore服务从Hive服务里剥离出来,Metastore独立安装在一个集群里,Hive远程调用Metastore服务,这样我们可以把元数据这一层放到防火墙之后,客户端访问Hive服务,就可以连接到元数据这一层,从而提供了更好的管理性和安全保障。使用远程的Metastore服务,可以让Metastore服务和hive服务运行在不同的进程里,这样也保证了Hive的稳定性,提升了Hive服务的效率。

     

    Hive的执行流程如下图所示:


    Hive的执行流程图

     

    1.3 前置条件

    Hive是建立Hadoop环境安装之上的,所以需要Hadoop的集群环境搭建,Hive即需要依赖于HDFS又需要依赖YARN。安装好Hadoop后需要进行启动HDFSYARN

    环境安装参考资料:

    1、安装《VMware安装Linux教程》地址:http://blog.csdn.net/yuan_xw/article/details/49827477

    2、安装《Linux网络配置与远程连接》地址:http://blog.csdn.net/yuan_xw/article/details/49945007

    3、安装《Hadoop教程()Hadoop分布式集群部署安装》

    地址:http://blog.csdn.net/yuan_xw/article/details/51175171

    4、安装《MySQL环境安装()》地址:http://blog.csdn.net/yuan_xw/article/details/77983704

     

    5、Hive规划图

    主机名

    IP

    安装软件

    运行进程

    Hadoop1

    192.168.197.128

    JdkHadoop

    NameNodeDFSZKFailoverController

    Hadoop2

    192.168.197.129

    JdkHadoop

    NameNodeDFSZKFailoverController

    Hadoop3

    192.168.197.130

    JdkHadoop

    ResourceManagerHiveMySQL

    Hadoop4

    192.168.197.131

    JdkHadoopZookeep

    DataNodeNodeManagerJournalNodeQuorumPeerMain

    Hadoop5

    192.168.197.132

    JdkHadoopZookeep

    DataNodeNodeManagerJournalNodeQuorumPeerMain

    Hadoop6

    192.168.197.133

    JdkHadoopZookeep

    DataNodeNodeManagerJournalNodeQuorumPeerMain

     

    环境安装参考资料:

    1、Hive下载地址:http://mirror.bit.edu.cn/apache/hive/hive-2.3.0/apache-hive-2.3.0-bin.tar.gz

    2、HadoopHbase版本关系表:

    Hive版本

    Hadoop版本

    Hive-2.3.0

    2.x.y

    Hive-2.2.0

    2.x.y

    Hive-2.1.1

    2.x.y

    Hive-2.1.0

    2.x.y

    Hive-2.0.0

    2.x.y

    Hive-1.2.2

    1.x.y2.x.y

    Hive-1.2.1

    1.x.y2.x.y

    Hive-1.0.1

    1.x.y2.x.y

    Hive-1.1.1

    1.x.y2.x.y

    Hive-1.0.1

    1.x.y2.x.y

    Hive-1.0.0

    1.x.y2.x.y

    Hive-0.13.1

    0.20.x 0.23.x.y1.x.y 2.x.y

    Hive-0.13.0

    0.20.x 0.23.x.y1.x.y 2.x.y

    Hive-0.12.0

    0.20.x 0.23.x.y1.x.y 2.x.y

    Hive-0.11.0

    0.20.x 0.23.x.y1.x.y 2.x.y

    Hive-0.10.0

    0.20.x 0.23.x.y1.x.y 2.x.y

     

    1.4 下载Hive

    1、Hive下载:

    执行命令:wget http://mirror.bit.edu.cn/apache/hive/hive-2.3.0/apache-hive-2.3.0-bin.tar.gz


     

    2、解压Hive

    bin:包含hive的命令shell脚本

    binary-package-licenses:包含了LICENSE说明文件

    conf:包含hive配置文件

    examples:包含了示例

    hcatalogMetastore操作的元数据目录

    jdbc:提供了hive-jdbc-2.3.0-standalone.jar

    scripts:提供了sql脚本


     

    3、修改环境变量:

    执行命令:vi /etc/profile

    export JAVA_HOME=/usr/local/software/jdk1.8.0_66

    export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

    export HADOOP_HOME=/usr/local/software/hadoop_2.7.1

    export HBASE_HOME=/usr/local/software/hbase_1.2.2

    export HIVE_HOME=/usr/local/software/apache-hive-2.3.0-bin

    export PATH=.:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HBASE_HOME/bin:$HIVE_HOME/bin:$PATH

    执行命令:source /etc/profile   刷新环境变量

    1.5 修改Hive配置文件

    1、修改hive-site.xml配置文件:

    执行命令:

    cd/usr/local/software/apache-hive-2.3.0-bin/conf/

    mv hive-default.xml.templatehive-site.xml


    2、新建 hdfs目录

    使用 hadoop新建 hdfs目录,因为在 hive-site.xml中有默认如下配置:

    <property>
    	<name>hive.metastore.warehouse.dir</name>
    	<value>/user/hive/warehouse</value>
    	<description>location of defaultdatabase for the warehouse</description>
    </property>

    3、进入 hadoop安装目录执行hadoop命令新建/user/hive/warehouse目录,并授权,用于存储文件

    hadoop fs -mkdir -p /user/hive/warehouse

    hadoop fs -mkdir -p /user/hive/tmp

    hadoop fs -mkdir -p /user/hive/log

    hadoop fs -chmod -R 777 /user/hive/warehouse

    hadoop fs -chmod -R 777 /user/hive/tmp

    hadoop fs -chmod -R 777 /user/hive/log

     

    # 用以下命令检查目录是否创建成功

    hadoop fs -ls /user/hive


     

    4、修改 hive-site.xml

    搜索hive.exec.scratchdir,将该name对应的value修改为/user/hive/tmp

    <property>
    	<name>hive.exec.scratchdir</name>
    	<value>/user/hive/tmp</value>
    </property>

    搜索hive.querylog.location,将该name对应的value修改为/user/hive/log/hadoop

    <property>
    	<name>hive.querylog.location</name>
    	<value>/user/hive/log/hadoop</value>
    	<description>Location of Hive run time structured logfile</description>
    </property>

    搜索javax.jdo.option.connectionURL,将该name对应的value修改为MySQL的地址

    <property>
    	<name>javax.jdo.option.ConnectionURL</name>
    	<value>jdbc:mysql://127.0.0.1:3306/hive?createDatabaseIfNotExist=true</value>
    	<description>
    		JDBC connectstring for a JDBC metastore.
    		To use SSL toencrypt/authenticate the connection, provide
    		database-specific SSL flag in theconnection URL.
    		For example,jdbc:postgresql://myhost/db?ssl=true for postgres database.
    	</description>
    </property>

    搜索javax.jdo.option.ConnectionDriverName,将该name对应的value修改为MySQL驱动类路径

    <property>
    	<name>javax.jdo.option.ConnectionDriverName</name>
    	<value>com.mysql.jdbc.Driver</value>
    	<description>Driverclass name for a JDBC metastore</description>
    </property>

    搜索javax.jdo.option.ConnectionUserName,将对应的value修改为MySQL数据库登录名

    <property>
    	<name>javax.jdo.option.ConnectionUserName</name>
    	<value>root</value>
    	<description>Username touse against metastore database</description>
    </property>

    搜索javax.jdo.option.ConnectionPassword,将对应的value修改为MySQL数据库的登录密码

    <property>
    	<name>javax.jdo.option.ConnectionPassword</name>
    	<value>root</value>
    	<description>password to useagainst metastore database</description>
    </property>

    创建tmp目录

    执行命令:mkdir -p/usr/local/software/apache-hive-2.3.0-bin/tmp


    5、修改 hive-site.xml

    ${system:java.io.tmpdir}改成/usr/local/software/apache-hive-2.3.0-bin/tmp

    ${system:user.name}改成${user.name}


    6、修改hive-env.sh

    mv hive-env.sh.template hive-env.sh

    HADOOP_HOME=/usr/local/software/hadoop_2.7.1

    export HIVE_CONF_DIR=/usr/local/software/apache-hive-2.3.0-bin/conf



    7、下载 mysql驱动包

    执行命令:

    cd/usr/local/software/apache-hive-2.3.0-bin/lib/

    wget http://central.maven.org/maven2/mysql/mysql-connector-java/5.1.38/mysql-connector-java-5.1.38.jar

     


    1.6 初始化MySQL

    1、MySQL数据库进行初始化,首先确保 mysql 中已经创建 hive库:

    执行命令:

    cd /usr/local/software/apache-hive-2.3.0-bin/bin

     ./schematool-initSchema -dbType mysql


                  看到红框的内容表示初始化成功。

    2、MySQL数据库进行初始化,首先确保 mysql 中已经创建 hive库:


    3、查看hive库中所有的表


     

    1.7 启动Hive

    1、启动Hive

    执行命令:/usr/local/software/apache-hive-2.3.0-bin/bin/hive


                  在命令行显示:OK表示已经查看数据库成功。

     

    1.8 学习Hive推荐书籍:

    1. Hive编程指南》

    2. Hadoop应用架构》

    3. Hadoop技术内幕:深入解析Hadoop CommonHDFS架构设计与实现原理》

    4. Hadoop技术内幕:深入解析MapReduce架构设计与实现原理》

    5. Hadoop技术内幕:深入解析YARN架构设计与实现原理》

     

     

                    --以上为《Hive教程(一) Hive入门教程》,如有不当之处请指出,我后续逐步完善更正,大家共同提高。谢谢大家对我的关注。

                                                                                                                                                                                          ——厚积薄发(yuanxw)


    展开全文
  • mfc最详细入门教程

    万次阅读 多人点赞 2017-11-24 10:07:52
    以下是我从其他网站中学的内容,后有相应的网站学习链接地址,可供学习 1.选择菜单项File->New->Project,弹出“New Project”对话框。  2.左侧面板中Installed Templated的Visual C++下选择MFC,中间窗口中...

    以下是我从其他网站中学的内容,后有相应的网站学习链接地址,可供学习

    1.选择菜单项File->New->Project,弹出“New Project”对话框。

     2.左侧面板中Installed Templated的Visual C++下选择MFC,中间窗口中选择MFC Application,然后在下面的Name编辑框中键入工程名称,本例取名“Addition”,在Location编辑框中设置工程的保存路径。点“OK”。

     3.点“Next”到“Application Type”对话框,在Application type下选择Dialog based,其他使用默认设置,点“Finish”。

     我们可以在Solution Explorer视图中看到,此工程的文件要比单文档应用程序少的多,在Class View中主要有三个类:CAboutDlg、CAdditionApp和CAdditionDlg。CAboutDlg是应用程序的“关于”对话框类,CAdditionApp是由CWinApp派生的类,CAdditionDlg是主对话框类,主对话框也就是此应用程序运行后显示的主要界面。

    在Resource View视图中可以看到工程Addition的资源树,展开Addition.rc,下面有四个子项:Dialog(对话框)、Icon(图标)、String Table(字符串表)和Version(版本)。然后展开Dialog项,下面有两个对话框模板,其ID分别为:IDD_ABOUTBOX和IDD_ADDITION_DIALOG,前者是“关于”对话框的模板,后者是主对话框的模板。ID是资源的唯一标识,本质上是一个无符号整数,一般ID代表的整数值由系统定义,我们无需干涉。

    可见对于主对话框来说,创建对话框第一步中的创建新的对话框模板已经由系统自动完成了。而如果是再添加对话框需要创建新的对话框模板时,需要在Resource View的“Dialog”节点上点右键,在右键菜单中选择“Insert Dialog”,就会生成新的对话框模板,并且会自动分配ID。

    在Resource View的资源树中双击某个ID,可在中间区域内显示相应的资源界面。双击IDD_ADDITION_DIALOG时,中间区域就会显示Addition对话框模板。如下图:

    VS2010/MFC编程入门之六(对话框:创建对话框模板和修改对话框属性)



    在Addition对话框模板上点右键,然后在右键菜单中选择Properties,则在右侧面板中会显示对话框的属性列表。如下图:

    VS2010/MFC编程入门之六(对话框:创建对话框模板和修改对话框属性)

      1.ID:对话框ID,唯一标识对话框资源,可以修改。此处为IDD_ADDITION_DIALOG,我们不修改它。

    2.Caption:对话框标题。此处默认为Addition,我们将其修改为“加法计算器”。

    3.Border:边框类型。有四种类型:None、Thin、Resizing和Dialog Frame。我们使用默认的Dialog Frame。

           4.Maximize:是否使用最大化按钮。我们使用默认的False。

           5.Minimize:是否使用最小化按钮。同样我们使用默认的False。

           6.Style:对话框类型。有三种类型:Overlapped(重叠窗口)、Popup(弹出式窗口)和Child(子窗口)。弹出式窗口比较常见。我们使用默认的Popup类型。

           7.System Menu:是否带有标题栏左上角的系统菜单,包括移动、关闭等菜单项。我们使用默认的True。

           8.Title Bar:是否带有标题栏。我们使用默认的True。

           9.Font(Size):字体类型和字体大小。如果将其修改为非系统字体,则Use System自动改为False。而如果Use System原来为False,将其修改为True,则Font(Size)自动设置为系统字体。这里我们使用默认的系统字体。

           根据以上说明,其实我们只修改了标题属性。这时我们运行此程序后的界面如下:

    VS2010/MFC编程入门之六(对话框:创建对话框模板和修改对话框属性)

     1.为对话框添加一个静态文本框(Static Text),用于显示字符串--“被加数”。

          对于自动添加的一个标题为“TODO:Place dialog controls here.”的静态文本框,这里将它删掉,继续添加新的静态文本框。

           删除控件时,可以使用鼠标左键点击选中它,选中后控件的周围会出现虚线框,然后按Delete键就可以将其删除了。在“Addition”工程的Resource View中打开上一讲中创建的对话框模板IDD_ADDITION_DIALOG,自动添加的静态文本框就可以使用这种方法删除。

           在添加新的静态文本框以前,先看看Toolbox视图是否显示了,如果没有显示,在菜单栏上点击View->Toolbox即可。Toolbox视图如下图:

    VS2010/MFC编程入门之七(对话框:为对话框添加控件)

           Toolbox中列出了一些常用控件,其中有一个是Static Text,即是我们要添加的控件。在Toolbox中的Static Text上点下鼠标左键不放开,并拖到IDD_ADDITION_DIALOG对话框模板上,模板上会出现一个虚线框,我们找到合适的位置松开鼠标左键放下它。

           用鼠标左键选中控件后周围出现虚线框,然后鼠标移到虚线框上几个黑点的位置会变成双向箭头的形状,此时就可以按下鼠标左键并拖动来改变控件大小了。我们可以这样改变新添加的静态文本框控件的大小,以更好的显示标题。当然,整个对话框模板也可以用这种方法改变大小。

           接下来就该修改静态文本框的文字了。鼠标右键点击静态文本框,在右键菜单中选择“Properties”,Properties面板就会显示出来,在面板上修改Caption属性为“被加数”,ID修改为IDC_SUMMAND_STATIC。此时模板如下图:

    VS2010/MFC编程入门之七(对话框:为对话框添加控件)

           2.为对话框添加一个编辑框(Edit Control),用来输入被加数。

           添加编辑框的过程与静态文本框类似,在Toolbox中选中Edit Control控件拖到对话框模板上,并使其与之前的静态文本框水平对齐(为了美观),然后调整其大小使之适合被加数的输入。

           在编辑框上点右键,仍然在右键菜单中选择“Properties”显示出属性(Properties)面板,修改其ID为IDC_SUMMAND_EDIT。此时模板如下图:

    VS2010/MFC编程入门之七(对话框:为对话框添加控件)

           3.按照1的方法添加一个标题为“加数”的静态文本框,用于显示字符串--“加数”。并将其ID改为IDC_ADDEND_STATIC。

           4.按照2的方法添加一个ID为IDC_ADDEND_EDIT的编辑框,用来输入加数。

           5.按照1的方法添加一个标题为“和”的静态文本框,用于显示文字--“和”。并修改其ID为IDC_SUM_STATIC。

           6.按照2的方法添加一个ID为IDC_SUM_EDIT的编辑框,用来显示最终的加和。

           7.类似的添加按钮(Button)控件到对话框模板,用于在被点击后触发加法计算。修改其标题为“计算”,ID为IDC_ADD_BUTTON。

           到此,对话框模板如图:

    VS2010/MFC编程入门之七(对话框:为对话框添加控件)

           8.删除OK按钮。打开Cancel按钮的属性面板,将标题改为“退出”,并使其与“计算”按钮水平对齐。

           9.根据控件的布局,适当调整整个对话框模板的大小,使其相对控件布局来说大小合适,界面美观。

           这样在对话框模板中就把我们在本例中需要用到的控件就添加完了。最终效果如下:

    VS2010/MFC编程入门之七(对话框:为对话框添加控件)

     因为例程Addition是基于对话框的程序,所以程序自动创建了对话框模板IDD_ADDITION_DIALOG,并自动生成了对话框类CAdditionDlg,它是从CDialogEx类派生的。大家用过VC++ 6.0的可能记得,我们定义的对话框类都是从CDialog类派生的,但在VS2010中,一般对话框类都是继承自CDialogEx类。

           创建对话框类

           如果是自己新添加的对话框模板,怎样为它创建对话框类呢?

           1.在Resource View的“Dialog”节点上右键,然后在右键菜单中选择“Insert Dialog”创建一个新的对话框模板,ID就使用默认的IDD_DIALOG1。

           2.在中间区域会显示新建的对话框模板,然后选中此对话框模板,点右键,在右键菜单中选择Add Class。

     VS2010/MFC编程入门之八(对话框:创建对话框类和添加控件变量)

           3.选择“Add Class”后会弹出一个对话框,在对话框中“Class name”下的编辑框中写入自定义的类名就可以了,例如CMyDialog。

           4.最后点“Finish”完成。

           最终你就可以在Class View中看到新生成的对话框类CMyDialog了,并且在Solution Explorer中有相应的MyDialog.h头文件和MyDialog.cpp源文件生成。CMyDialog类同样派生于CDialogEx类。

           注意,一般类名都以C打头,又比如,CTestDlg。


           为对话框中的控件添加变量

           在上一讲中为对话框添加了几个控件,包括三个静态文本框,三个编辑框,一个按钮控件。程序自动生成的Cancel按钮保留,作为退出按钮,而OK按钮删除掉了。

           静态文本框只是为了说明后面紧跟的编辑框中数据的意义,是被加数、加数还是和,所以它们是不会变的,我们就不为它们添加变量了。按钮控件是用来操作的,这里也不为它们添加变量。编辑框中的数据可能会经常变化,有必要为它们每个控件关联一个变量。

           首先为被加数的编辑框IDC_SUMMAND_EDIT添加变量。

           1.在编辑框上点右键,在右键菜单中选择“Add Variable”。弹出添加成员变量的向导对话框。

           2.我们想为其添加值变量而不是控件变量,所以对话框中“Category”下的组合框中选择Value。

           3.“Variable type”下的组合框此时默认选中的是“CString”,CString是字符串类,显然不能进行加法运算。我们可以选择double、float、int等。这里我们选择double,即编辑框关联一个double类型的变量。

           4.在“Variable name”中写入自定义的变量名。鸡啄米为其取名m_editSummand。

    VS2010/MFC编程入门之八(对话框:创建对话框类和添加控件变量)

           5.点“Finish”完成。

           注意,类的成员变量名一般以m_打头,以标识它是一个成员变量。

           参照此方法,再分别为加数的编辑框IDD_ADDEND_EDIT添加double型变量m_editAddend、和的编辑框IDD_SUM_EDIT添加double型变量m_editSum。

           对话框类的数据交换和检验

           在程序运行界面中,用户往往会改变控件的属性,例如,在编辑框中输入字符串,或者改变组合框的选中项,又或者改变复选框的选中状态等。控件的属性改变后MFC会相应修改控件关联变量的值。这种同步的改变是通过MFC为对话框类自动生成的成员函数DoDataExchange()来实现的,这也叫做对话框的数据交换和检验机制。

           我们为三个编辑框添加了变量以后,在AdditionDlg.cpp中CAdditionDlg的DoDataExchange()函数的函数体中多了三条DDX_Text调用语句。下面是函数体代码和鸡啄米添加的注释。

    C++代码
    1. void CAdditionDlg::DoDataExchange(CDataExchange* pDX)   
    2. {   
    3.     // 处理MFC默认的数据交换   
    4.     CDialogEx::DoDataExchange(pDX);   
    5.     // 处理控件IDC_SUMMAND_EDIT和变量m_editSummand之间的数据交换   
    6.     DDX_Text(pDX, IDC_SUMMAND_EDIT, m_editSummand);   
    7.     // 处理控件IDC_ADDEND_EDIT和变量m_editAddend之间的数据交换   
    8.     DDX_Text(pDX, IDC_ADDEND_EDIT, m_editAddend);   
    9.     // 处理控件IDC_SUM_EDIT和变量m_editSum之间的数据交换   
    10.     DDX_Text(pDX, IDC_SUM_EDIT, m_editSum);   
    11. }  

           再以Addition程序为例简单说下数据交换机制。如果我们在程序运行界面中输入被加数,则通过CAddition的DoDataExchange()函数可以将输入的值保存到m_editSummand变量中,反之如果程序运行中修改了变量m_editSummand的值,则通过CAddition的DoDataExchange()函数也可以将新的变量值显示到被加数的编辑框中。

           但是这种数据交换机制中,DoDataExchange()并不是被自动调用的,而是需要我们在程序中调用CDialogEx::UpdateData()函数,由UpdateData()函数再去自动调用DoDataExchange()的。

           CDialogEx::UpdateData()函数的原型为:

           BOOL UpdateData(BOOL bSaveAndValidate = TRUE);

           参数:bSaveAndValidate用于指示数据传输的方向,TRUE表示从控件传给变量,FALSE表示从变量传给控件。默认值是TRUE,即从控件传给变量。

           返回值:CDialogEx::UpdateData()函数的返回值表示操作是否成功,成功则返回TRUE,否则返回FALSE。

           在下一讲中将具体演示CDialogEx::UpdateData()函数如何使用。

           鸡啄米本节主要讲的是新建对话框类和添加控件变量,控件的消息处理函数将在下一讲详细介绍。

    *********************************************************************************************************************************************************************

     创建对话框类和添加控件变量在上一讲中已经讲过,这一讲的主要内容是如何为控件添加消息处理函数。

           MFC为对话框和控件等定义了诸多消息,我们对它们操作时会触发消息,这些消息最终由消息处理函数处理。比如我们点击按钮时就会产生BN_CLICKED消息,修改编辑框内容时会产生EN_CHANGE消息等。一般为了让某种操作达到效果,我们只需要实现某个消息的消息处理函数。

           一.添加消息处理函数

           鸡啄米仍以前面的加法计算器的程序为例,说明怎样为“计算”按钮控件添加消息处理函数。添加方法列出4种:

           1.使用Class Wizard添加消息处理函数

           用过的VC++ 6.0的朋友应该对Class Wizard很熟悉了,添加、消息处理函数等经常会用到它,可以说是一个很核心的功能。但从VS2002开始就见不到Class Wizard了,大部分功能都集成到对话框和控件等的属性中了,使用很方便。到VS2010,久违的Class Wizard又回来了。但鸡啄米已经习惯了使用属性中的功能了,对于从VC++ 6.0直接转VS2010的朋友可能觉得还是使用Class Wizard比较习惯。

    VS2010/MFC编程入门之九(对话框:为控件添加消息处理函数)

           大家应该记得,“计算”按钮的ID为IDC_ADD_BUTTON,上图中Commands标签下,Oject IDs列表中有此ID,因为我们是想实现点击按钮后的消息处理函数,所以在Messages列表中选择BN_CLICKED消息,然后点右上方的Add Handler就可以添加BN_CLICKED消息处理函数OnClickedAddButton了。当然你也可以改名,但一般用的默认的就可以。

           2.通过“Add Event Handler...”添加消息处理函数

           在“计算”按钮上点右键,然后在右键菜单中选择菜单项“Add Event Handler...”,弹出“Event Handler Wizard”对话框,如下图:

    VS2010/MFC编程入门之九(对话框:为控件添加消息处理函数)

           可见“Message type”中默认选中的就是BN_CLICKED消息,函数名和所在类都已经自动给出,直接点“Add and Edit”就可以了。

           3.在按钮的属性视图中添加消息处理函数

           上面说过,从VS2002开始就主要从属性视图添加消息处理函数了。我们在“计算”按钮上点右键,在右键菜单中选择“Properties”,右侧面板中会显示按钮的属性视图。

    VS2010/MFC编程入门之九(对话框:为控件添加消息处理函数)

           我们可以像上图中那样,点属性视图的“Control Events”按钮(类似闪电标志),下面列出了“计算”按钮的所有消息。我们要处理的是BN_CLICKED消息,点其右侧空白列表项,会出现一个带下箭头的按钮,再点此按钮会出现“<Add> OnBnClickedAddButton”选项,最后选中这个选项就会自动添加BN_CLICKED处理函数了。

           4.双击按钮添加消息处理函数

           最直接最简单的方法就是,双击“计算”按钮,MFC会自动为其在CAdditionDlg类中添加BN_CLICKED消息的处理函数OnBnClickedAddButton()。

           二.在消息处理函数中添加自定义功能

           在我们使用任意一种方法添加了消息处理函数以后,都只能得到一个空的OnBnClickedAddButton()函数的函数体,要实现我们想要的功能,还需要在函数体中加入自定义功能代码。

           在加法计算器程序中,我们想要“计算”按钮实现的功能是,获取被加数和加数的数值,然后计算它们的和并显示到和的编辑框里。那么,OnBnClickedAddButton()的函数体就应修改为:

    C++代码
    1. void CAdditionDlg::OnBnClickedAddButton()   
    2. {   
    3.     // TODO: Add your control notification handler code here   
    4.     // 将各控件中的数据保存到相应的变量   
    5.     UpdateData(TRUE);   
    6.   
    7.     // 将被加数和加数的加和赋值给m_editSum   
    8.     m_editSum = m_editSummand + m_editAddend;   
    9.   
    10.     // 根据各变量的值更新相应的控件。和的编辑框会显示m_editSum的值   
    11.     UpdateData(FALSE);   
    12. }  

           鸡啄米在上面的代码中已经添加注释,大家应该很容易理解了。对于UpdateData()函数的说明在上一讲中已经介绍过,如果忘了可以再回上一讲了解了解。

           接下来我们运行下此应用程序。在运行结果界面中,输入被加数5.1,加数2.3,然后点“计算”:

    VS2010/MFC编程入门之九(对话框:为控件添加消息处理函数)

           在上图中可以看到,点“计算”按钮后,和的编辑框中显示了正确结果:7.4。

           鸡啄米简单分析下运行过程:输入被加数和加数,点“计算”按钮后产生点击消息,从而调用OnBnClickedAddButton()函数。进入此函数后,首先由UpdateData(TRUE)函数将被加数的值5.1和加数的值2.3分别保存到变量m_editSummand和m_editAddend,然后通过语句m_editSum = m_editSummand + m_editAddend;计算出被加数和加数的和为7.4,并把7.4赋值给m_editSum。最后调用UpdateData(FALSE)根据被加数、加数、和的值更新三个编辑框的显示值,就得到了上图中的结果。

           到此,一个具有简单的加法运算功能的加法计算器应用程序就基本完成了。

    ************************************************************************************************************************************************************************

    本节主要讲对话框上控件的Tab顺序如何调整

           上一讲为“计算”按钮添加了消息处理函数后,加法计算器已经能够进行浮点数的加法运算。但是还有个遗留的小问题,就是对话框控件的Tab顺序问题。

           运行加法计算器程序,显示对话框后不进行任何操作,直接按回车,可以看到对话框退出了。这是因为“退出”按钮是Tab顺序为1的控件,也就是第一个接受用户输入的控件。但是按照我们的输入习惯,应该是被加数的编辑框首先接受用户输入,然后是加数编辑框,再接下来是“计算”按钮,最后才是“退出”按钮。

           我们先来直观的看看各个控件的Tab顺序吧。打开“Resource View”视图,然后在资源中找到对话框IDD_ADDITION_DIALOG,双击ID后中间客户区域出现其模板视图。在主菜单中选择“Format”->"Tab Order",或者按快捷键Ctrl+D,对话框模板上就会显示各个控件的Tab顺序数字。如下图:

    VS2010/MFC编程入门之十(对话框:设置对话框控件的Tab顺序)

           上图中每个控件左上角都有一个数字,这就是它的Tab响应顺序。对话框刚打开时输入焦点就在Tab顺序为1的“退出”按钮上,不做任何操作按下Tab键,输入焦点就会转移到Tab顺序为2的“被加数”静态文本框上,但是因为静态文本框不接受任何输入,所以输入焦点继续自动转移到Tab顺序为3的被加数编辑框,再按Tab键,输入焦点又会转移到Tab顺序为4的“加数”静态文本框上,同样由于它是静态文本框,输入焦点不停留继续转移到加数编辑框,后面的控件同理。

           我们认为这个顺序不合理,那怎么修改呢?很简单,从自己认为Tab顺序应该为1的控件开始依次单击,随着单击的完成,各控件的Tab响应顺序也按我们的想法设置好了。

           例如,此例中我们可以依次单击被加数编辑框、“被加数”静态文本框、加数编辑框、“加数”静态文本框、和编辑框、“和”静态文本框、“计算”按钮和“退出”按钮。设置完后如下图:

    VS2010/MFC编程入门之十(对话框:设置对话框控件的Tab顺序)

           最后按ESC键,确认设置并退出对话框模板的Tab顺序设置状态。

           现在我们再运行程序,可以看到对话框打开后最初的输入焦点在被加数编辑框上,然后我们按Tab键,输入焦点移到加数编辑框上,继续多次按Tab键时,输入焦点会按“和编辑框--‘计算’按钮--‘退出’按钮--被加数编辑框--加数编辑框--和编辑框......”的顺序循环转移。这样就达到了我们的目的。

    *******************************************************************************************************************************************************************************************

    加法计算器对话框程序大家照着做一遍后,相信对基于对话框的程序有些了解了,有个好的开始对于以后的学习大有裨益。趁热打铁,鸡啄米这一节讲讲什么是模态对话框和非模态对话框,以及模态对话框怎样弹出。

           一.模态对话框和非模态对话框

           Windows对话框分为两类:模态对话框和非模态对话框。

           模态对话框是这样的对话框,当它弹出后,本应用程序其他窗口将不再接受用户输入,只有该对话框响应用户输入,在对它进行相应操作退出后,其他窗口才能继续与用户交互。

           非模态对话框则是,它弹出后,本程序其他窗口仍能响应用户输入。非模态对话框一般用来显示提示信息等。

           大家对Windows系统很了解,相信这两种对话框应该都遇到过。之前的加法计算器对话框其实就是模态对话框。

           二.模态对话框是怎样弹出的

           毕竟加法计算器程序大部分都是MFC自动生成的,对话框怎么弹出来的大家可能还不是很清楚。鸡啄米下面简单说说它是在哪里弹出来的,再重新建一个新的对话框并弹出它,这样大家实践以后就能更灵活的使用模态对话框了。

           大家打开Addition.cpp文件,可以看到CAdditionApp类有个InitInstance()函数,在MFC应用程序框架分析中提到过此函数,不过那是单文档应用程序App类中的,函数体不太相同,但都是进行App类实例的初始化工作。

           InitInstance()函数的后半部分有一段代码就是定义对话框对象并弹出对话框的,鸡啄米下面给出这段代码并加以注释:

    C++代码
    1. CAdditionDlg dlg;        // 定义对话框类CAdditionDlg的对象dlg   
    2. m_pMainWnd = &dlg;       // 将dlg设为主窗口   
    3. INT_PTR nResponse = dlg.DoModal();   // 弹出对话框dlg,并将DoModal函数的返回值(退出时点击按钮的ID)赋值给nResponse   
    4. if (nResponse == IDOK)               // 判断返回值是否为OK按钮(其ID为IDOK,鸡啄米已经将它删除)   
    5. {   
    6.     // TODO: Place code here to handle when the dialog is   
    7.     //  dismissed with OK   
    8. }   
    9. else if (nResponse == IDCANCEL)      // 判断返回值是否为Cancel按钮(其ID为IDCANCEL,鸡啄米将它的Caption改为了“退出”)   
    10. {   
    11.     // TODO: Place code here to handle when the dialog is   
    12.     //  dismissed with Cancel   
    13. }  

           弹出对话框比较关键的一个函数,就是对话框类的DoModal()函数。CDialog::DoModal()函数的原型为:

           virtual INT_PTR DoModal();   

           返回值:整数值,指定了传递给CDialog::EndDialog(该函数用于关闭对话框)的nResult参数值。如果函数不能创建对话框,则返回-1;如果出现其它错误,则返回IDABORT。

           调用了它对话框就会弹出,返回值是退出对话框时所点的按钮的ID,比如,我们点了“退出”按钮,那么DoModal返回值为IDCANCEL。

           三.添加一个新对话框并弹出它

           鸡啄米再为加法计算器程序添加一个对话框,以在计算之前询问用户是否确定要进行计算。大家可以完整的看下对话框的添加和弹出过程。

           1.在Resource View中的“Dialog”上点右键选择“Insert Dialog”,创建一个新的对话框模板,修改其ID为IDD_TIP_DIALOG,Caption改为“提示”,然后参考“为对话框添加控件”中所讲,在对话框模板上添加一个静态文本框(static text),Caption改为“您确定要进行加法计算吗?”,接下来修改OK按钮的Caption为“确定”,Cancel按钮的Caption为“取消”,最后调整各个控件的位置和对话框的大小。最终的对话框模板如下图:

    VS2010/MFC编程入门之十一(对话框:模态对话框及其弹出过程)

           2.根据“创建对话框类和添加控件变量”中创建对话框类的方法,在对话框模板上点右键选择“Add Class...”,弹出添加类的对话框,设置“Class name”为CTipDlg,点“OK”。在Solution Explorer中可以看到生成了CTipDlg类的头文件TipDlg.h和源文件TipDlg.cpp。

           3.我们要在点“计算”按钮之后弹出此提示对话框,那么就要在“计算”按钮的消息处理函数OnBnClickedAddButton()中访问提示对话框类,所以为了访问CTipDlg类,在AdditionDlg.cpp中包含CTipDlg的头文件:#include "TipDlg.h"。

           4.修改OnBnClickedAddButton()的函数体,在所有代码前,构造CTipDlg类的对象tipDlg,并通过语句tipDlg.DoModal();弹出对话框,最后判断DoModal()函数的返回值是IDOK还是IDCANCEL来确定是否继续进行计算。OnBnClickedAddButton()函数修改后如下:

    C++代码
    1. void CAdditionDlg::OnBnClickedAddButton()   
    2. {   
    3.     // TODO: Add your control notification handler code here   
    4.     INT_PTR nRes;             // 用于保存DoModal函数的返回值   
    5.   
    6.     CTipDlg tipDlg;           // 构造对话框类CTipDlg的实例   
    7.     nRes = tipDlg.DoModal();  // 弹出对话框   
    8.     if (IDCANCEL == nRes)     // 判断对话框退出后返回值是否为IDCANCEL,如果是则return,否则继续向下执行   
    9.         return;   
    10.   
    11.     // 将各控件中的数据保存到相应的变量   
    12.     UpdateData(TRUE);   
    13.   
    14.     // 将被加数和加数的加和赋值给m_editSum   
    15.     m_editSum = m_editSummand + m_editAddend;   
    16.   
    17.     // 根据各变量的值更新相应的控件。和的编辑框会显示m_editSum的值   
    18.     UpdateData(FALSE);   
    19. }  

           5.测试。编译运行程序后,在对话框上输入被加数和加数,点“计算”,弹出提示对话框询问是否进行计算,如果选择“确定”,则提示对话框退出,并在主对话框上显示被加数和加数的和,而如果选择“取消”,则提示对话框也会退出,但主对话框显示的和不变,即没有进行加法计算。

    **********************************************************************************************************************************************************************

    本节接着讲另一种对话框--非模态对话框的创建及显示。

           鸡啄米已经说过,非模态对话框显示后,程序其他窗口仍能正常运行,可以响应用户输入,还可以相互切换。鸡啄米会将上一讲中创建的Tip模态对话框改为非模态对话框,让大家看下效果。

           非模态对话框的对话框资源对话框类

           实际上,模态对话框和非模态对话框在创建对话框资源和生成对话框类上是没有区别的,所以上一讲中创建的IDD_TIP_DIALOG对话框资源和CTipDlg类都不需要修改。

           创建及显示非模态对话框的步骤

           需要修改的是,对话框类实例的创建和显示,也就是之前在CAdditionDlg::OnBnClickedAddButton()函数体中添加的对话框显示代码。下面是具体步骤:

           1.在AdditionDlg.h中包含CTipDlg头文件并定义CTipDlg类型的指针成员变量。详细操作方法是,在AdditionDlg.cpp中删除之前添加的#include "TipDlg.h",而在AdditionDlg.h中添加#include "TipDlg.h",这是因为我们需要在AdditionDlg.h中定义CTipDlg类型的指针变量,所以要先包含它的头文件;然后在AdditionDlg.h中为CAdditionDlg类添加private成员变量CTipDlg  *m_pTipDlg;。

           2.在CAdditionDlg类的构造函数中初始化成员变量m_pTipDlg。如果cpp文件中函数太多,我们可以在Class View上半个视图中找到CAdditionDlg类,再在下半个视图中找到其构造函数双击,中间客户区域即可马上切到构造函数的实现处。在构造函数体中添加m_pTipDlg = NULL;,这是个好习惯,鸡啄米在C++编程入门系列的指针的赋值和指针运算中说到过,在任何指针变量使用前都初始化,可以避免因误访问重要内存地址而破坏此地址的数据。

           3.将上一讲中添加的模态对话框显示代码注释或删除掉,添加非模态对话框的创建和显示代码。VC++中注释单行代码使用“//”,注释多行代码可以在需注释的代码开始处添加“/*”,结束处添加“*/”。修改后的CAdditionDlg::OnBnClickedAddButton()函数如下:

    C++代码
    1. void CAdditionDlg::OnBnClickedAddButton()   
    2. {   
    3.     // TODO: Add your control notification handler code here   
    4.     /*INT_PTR nRes;             // 用于保存DoModal函数的返回值  
    5.  
    6.     CTipDlg tipDlg;           // 构造对话框类CTipDlg的实例  
    7.     nRes = tipDlg.DoModal();  // 弹出对话框  
    8.     if (IDCANCEL == nRes)     // 判断对话框退出后返回值是否为IDCANCEL,如果是则return,否则继续向下执行  
    9.         return;*/  
    10.   
    11.     // 如果指针变量m_pTipDlg的值为NULL,则对话框还未创建,需要动态创建   
    12.     if (NULL == m_pTipDlg)   
    13.     {   
    14.         // 创建非模态对话框实例   
    15.         m_pTipDlg = new CTipDlg();   
    16.         m_pTipDlg->Create(IDD_TIP_DIALOG, this);   
    17.     }   
    18.     // 显示非模态对话框   
    19.     m_pTipDlg->ShowWindow(SW_SHOW);   
    20.   
    21.     // 将各控件中的数据保存到相应的变量   
    22.     UpdateData(TRUE);   
    23.   
    24.     // 将被加数和加数的加和赋值给m_editSum   
    25.     m_editSum = m_editSummand + m_editAddend;   
    26.   
    27.     // 根据各变量的值更新相应的控件。和的编辑框会显示m_editSum的值   
    28.     UpdateData(FALSE);   
    29. }  

           4.因为此非模态对话框实例是动态创建的,所以需要手动删除此动态对象来销毁对话框。我们在CAdditionDlg类的析构函数中添加删除代码,但是MFC并没有自动给出析构函数,这时需要我们手动添加,在对话框对象析构时就会调用我们自定义的析构函数了。在AdditionDlg.h文件中为CAdditionDlg添加析构函数声明:~CAdditionDlg();,然后在AdditionDlg.cpp文件中添加析构函数的实现,函数体如下:

    C++代码
    1. CAdditionDlg::~CAdditionDlg()   
    2. {   
    3.     // 如果非模态对话框已经创建则删除它   
    4.     if (NULL != m_pTipDlg)   
    5.     {   
    6.         // 删除非模态对话框对象   
    7.         delete m_pTipDlg;   
    8.     }   
    9. }  

           这样,非模态对话框创建和显示的代码就添加修改完了。让我们运行下看看效果吧。

           在加法计算器对话框上输入被加数和加数,然后点“计算”按钮,依然像上节一样弹出了提示对话框,但是先不要关闭它,你可以拖动它后面的加法计算器对话框试试,我们发现加法计算器对话框竟然可以拖动了,而且“和”编辑框里已经显示了运算结果,这表明提示对话框显示以后还没有关闭,OnBnClickedAddButton() 就继续向下执行了,不仅如此,加法计算器的每个编辑框还都可以响应输入。

           这只是一个简单的例子,非模态对话框的用处有很多,以后大家在软件开发中会用到。

           本节教程就到这里了,相信大家对对话框的使用更上了一个台阶了,在不同的情况下可以选择使用模态对话框和非模态对话框了。鸡啄米欢迎大家留言讨论。

    ***************************************************************************************************************************************************************************

     前面讲了模态对话框非模态对话框,本节开始鸡啄米讲一种特殊的对话框--属性页对话框。另外,本套教程所讲大部分对VC++各个版本均可适用或者稍作修改即可,但考虑到终究还是基于VS2010版本的,所以将《VC++/MFC编程入门》改为《VS2010/MFC编程入门》。

           属性页对话框的分类

           属性页对话框想必大家并不陌生,XP系统中桌面右键点属性,弹出的就是属性页对话框,它通过标签切换各个页面。另外,我们在创建MFC工程时使用的向导对话框也属于属性页对话框,它通过点击“Next”等按钮来切换页面。

           属性页对话框就是包含一般属性页对话框和向导对话框两类。它将多个对话框集成于一身,通过标签或按钮来切换页面。

           属性页对话框相关类

          我们使用属性页对话框时,用到的类主要有两个:CPropertyPage类和CPropertySheet类。

           1.CPropertyPage类

           CPropertyPage类继承自CDialog类,它被用于处理某单个的属性页,所以要为每个属性页都创建一个继承自CPropertyPage的子类。大家可以在VS2010的MSDN中查找CPropertyPage类以及它的成员的详细说明。下面鸡啄米就为大家讲解MSDN中列出的CPropertyPage类的部分主要成员函数。

           (1)构造函数

            这里讲三个CProperty类的构造函数,函数原型为:

            CPropertyPage( );

            explicit CPropertyPage(
                    UINT nIDTemplate,
                    UINT nIDCaption = 0,
                    DWORD dwSize = sizeof(PROPSHEETPAGE)
            );

            explicit CPropertyPage(
                    LPCTSTR lpszTemplateName,
                    UINT nIDCaption = 0,
                    DWORD dwSize = sizeof(PROPSHEETPAGE)
            );

           第一个是没有任何参数的构造函数。

           第二个构造函数中,参数nIDTemplate是属性页的对话框资源ID,参数nIDCaption是属性页对话框选项卡的标题所用字符串资源的ID,若设为0,则选项卡标题就使用该属性页的对话框资源的标题。

           第三个构造函数中,参数lpszTemplateName为属性页的对话框资源的名称字符串,不能为NULL。参数nIDCaption同上。

          (2)CancelToClose()函数

           在模态属性页对话框的属性页进行了某不可恢复的操作后,使用CancelToClose()函数将“OK”按钮改为“Close”按钮,并禁用“Cancel”按钮。函数原型为:

           void CancelToClose( );

          (3)SetModified()函数

           调用此函数可激活或禁用“Apply”按钮,函数原型为:

           void SetModified(BOOL bChanged = TRUE);

          (4)可重载函数

           CPropertyPage类提供了一些消息处理函数,来响应属性页对话框的各种消息。我们重载这些消息处理函数,就可以自定义对属性页对话框操作的处理。可重载的消息处理函数包括:

           OnApply:处理属性页的“Apply”按钮被单击的消息
           OnCancel:处理属性页的“Cancel”按钮被单击的消息
           OnKillActive:处理属性页当前活动状态被切换的消息,常用于数据验证
           OnOK:处理属性页的“OK”按钮、“Apply”按钮或者“Close”按钮被单击的消息
           OnQueryCancel:处理属性页的“Cancel”按钮被单击前发出的消息
           OnReset:处理属性页的“Reset”按钮被单击的消息
           OnSetActive:处理属性页被切换为当前活动页的消息
           OnWizardBack:处理属性页的“Back”按钮被单击的消息,仅在向导对话框中有效
           OnWizardFinish:处理属性页的“Finish”按钮被单击的消息,仅在向导对话框中有效
           OnWizardNext:处理属性页的“Next”按钮被单击的消息,仅在向导对话框中有效

           2.CPropertySheet类

           CPropertySheet类继承自CWnd类,它是属性表类,负责加载、打开或删除属性页,并可以在属性页对话框中切换属性页。它跟对话框类似,也有模态和非模态两种。下面鸡啄米就讲解CPropertySheet类的部分成员函数。

          (1)构造函数

           这里依然列出CPropertySheet类的三个构造函数:

           CPropertySheet( );

           explicit CPropertySheet(
                   UINT nIDCaption,
                   CWnd* pParentWnd = NULL,
                   UINT iSelectPage = 0 
           );

           explicit CPropertySheet(
                   LPCTSTR pszCaption,
                   CWnd* pParentWnd = NULL,
                   UINT iSelectPage = 0 
           );

           参数nIDCaption:标题的字符串资源的ID。

           参数pParentWnd:属性页对话框的父窗口,若设为NULL,则父窗口为应用程序的主窗口。

           参数iSelectPage:初始状态时,活动属性页的索引,默认为第一个添加到属性表的属性页。

           参数pszCaption:标题字符串。

          (2)GetActiveIndex()函数

           获取当前活动属性页的索引。函数原型为:

           int GetActiveIndex( ) const;

           返回值:当前活动属性页的索引。

          (3)GetActivePage()函数

           获取当前活动属性页对象。函数原型为:

           CPropertyPage* GetActivePage( ) const;

           返回值:当前活动属性页对象的指针。

          (4)GetPage()函数

           获取某个属性页对象。函数原型为:

           CPropertyPage* GetPage(int nPage) const;

           参数nPage:目标属性页的索引。

           返回值:目标属性页对象的指针。

          (5)GetPageCount()函数

           获取属性页的数量。函数原型为:

           int GetPageCount( ) const;

           返回值:属性页的数量。

          (6)GetPageIndex()函数

           获取某属性页在属性页对话框中的索引。函数原型为:

           int GetPageIndex(CPropertyPage* pPage);

           参数pPage:要获取索引的属性页对象的指针。

           返回值:属性页对象在属性页对话框中的索引。

          (7)SetActivePage()函数

           设置某个属性页为活动属性页。函数原型为:   

           BOOL SetActivePage(
                     int nPage 
           );

           BOOL SetActivePage(
                     CPropertyPage* pPage 
           );

           参数nPage:要设置为活动属性页的索引。

           参数pPage:要设置为活动属性页的对象指针。

          (8)SetWizardButtons()函数

           在向导对话框上启用或禁用Back、Next或Finish按钮,应在调用DoModal之前调用此函数。函数原型为:

           void SetWizardButtons(
                    DWORD dwFlags 
           );

           参数dwFlags:设置向导按钮的外观和功能属性。可以是以下值的组合:

           PSWIZB_BACK                    启用“Back”按钮,如果不包含此值则禁用“Back”按钮。
           PSWIZB_NEXT                    启用“Next”按钮,如果不包含此值则禁用“Next”按钮。
           PSWIZB_FINISH                  启用“Finish”按钮。
           PSWIZB_DISABLEDFINISH   显示禁用的“Finish”按钮。

          (9)SetWizardMode()函数

           设置属性页对话框为向导对话框模式,应在调用DoModal之前调用此函数。函数原型为:

           void SetWizardMode( );

          (10)SetTitle()函数

           设置属性对话框的标题。函数原型为:

           void SetTitle(
                   LPCTSTR lpszText,
                   UINT nStyle = 0 
           );

           参数lpszText:标题字符串。

           参数nStyle:指定属性表标题的风格。应当为0或PSH_PROPTITLE。如果设为PSH_PROPTITLE,则单词“Properties”会出现在指定标题之后。例如,SetTitle("Simple",PSH_PROPTITLE)这种调用会使得属性表标题为“Simple Properties”。

          (11)AddPage()函数

           为属性对话框添加新的属性页。函数原型为:

           void AddPage(
                   CPropertyPage *pPage 
           );

           参数pPage:要添加的新的属性页的对象指针。

          (12)PressButton()函数

           模拟按下某指定的按钮。函数原型为:   

           void PressButton(
                   int nButton 
           );

           参数nButton:要模拟按下的按钮,它可以是下列值之一:

           PSBTN_BACK   选择“Back”按钮。 
           PSBTN_NEXT   选择“Next”按钮。
           PSBTN_FINISH   选择“Finish”按钮。
           PSBTN_OK   选择“OK”按钮。
           PSBTN_APPLYNOW   选择“Apply”按钮。
           PSBTN_CANCEL   选择“Cancel”按钮。
           PSBTN_HELP   选择“帮助”按钮。

          (13)RemovePage()函数

           删除某属性页。函数原型为:

           void RemovePage(
                   CPropertyPage *pPage 
           );

           void RemovePage(
                   int nPage 
           );

           参数pPage:要删除的属性页的对象指针。

           参数nPage:要删除的属性页的索引。

           属性对话框和相关的两个类鸡啄米就先介绍到这,主要是为后面使用属性页对话框做准备。有问题可以到鸡啄米博客交流。谢谢。

    *************************************************************************************************************************************************************************

    上一讲鸡啄米讲了属性页对话框和相关的两个类CPropertyPage类和CPropertySheet类,对使用属性页对话框做准备。本节将为大家演示如何创建向导对话框。

           仍然以前面的“加法计算器”的例子为基础,在其中加入向导对话框,我们可以用它来说明加法计算器的使用方法,一步一步引导用户操作,这也是比较常见的用法。

           加法计算器使用时大概可以分为三步:输入被加数、输入加数、点“计算”按钮。

           鸡啄米就详细说明向导对话框的创建步骤:

           1.创建属性页对话框资源

           根据创建对话框模板和修改对话框属性中所讲方法,在“Resource View”的Dialog”节点上点右键,然后在右键菜单中选择“Insert Dialog”创建第一个对话框模板,对话框的ID属性设置为IDD_SUMMAND_PAGE,Caption属性改为“被加数页”,Style属性在下拉列表中选择“Child”,Border属性在下拉列表中选择“Thin”。

           删除“OK”和“Cancel”按钮,再按照为对话框添加控件中所讲方法,添加一个静态文本框,并修改静态文本框的Caption属性为“请先输入double型被加数”。

           按照上述步骤,继续添加第二个和第三个对话框资源。第二个对话框模板的ID设为IDD_ADDEND_PAGE,Caption属性改为“加数页”,也添加一个静态文本框,Caption设为“请继续输入double型加数”,其他属性同第一个对话框。第三个对话框模板的ID设为IDD_ADD_PAGE,Caption属性改为“计算页”,添加静态文本框的Caption属性改为“最后请按下“计算”按钮”,其他属性也第一个对话框一样。

           2.创建属性页类

           按照创建对话框类和添加控件变量中的方法,在第一个对话框模板上点右键,在右键菜单中选择“Add Class”,弹出类向导对话框,在“Class name”编辑框中输入类名“CSummandPage”,与之前不同的是,因为属性页类都应继承于CPropertyPage类,所以要修改下面“Base class”的选项,在下拉列表中选择“CPropertyPage”。

           因为是第一个属性页,所以它应该有一个“下一步”按钮,在哪里添加呢?上一讲CPropertyPage类的可重载函数中提到,OnSetActive函数用于处理属性页被切换为当前活动页的消息,所以我们可以在OnSetActive函数中进行相关设置。

           那怎样重载OnSetActive函数呢?我们可以在“Class View”中找到“CSummandPage”节点,点右键弹出右键菜单,选择“Properties”,然后VS2010右侧面板上会显示对话框的属性列表,属性列表的工具栏上有个tip信息为“Overrides”的按钮,按下它,下方列表中就列出了重载函数,找到“OnSetActive”,点其右侧空白列表项出现向下箭头,再点箭头就在下面出现了“<Add>OnSetActive”的选项,选择它就会自动在CSummandPage类中添加函数OnSetActive。

     

           我们只需在OnSetActive函数体中添加相关代码就可以实现添加“下一步”按钮的效果了。新的函数体如下:

    C++代码
    1. BOOL CSummandPage::OnSetActive()   
    2. {   
    3.     // TODO: Add your specialized code here and/or call the base class  
    4.   
    5.     // 获得父窗口,即属性表CPropertySheet类   
    6.     CPropertySheet* psheet = (CPropertySheet*) GetParent();   
    7.     // 设置属性表只有“下一步”按钮   
    8.     psheet->SetWizardButtons(PSWIZB_NEXT);   
    9.   
    10.     return CPropertyPage::OnSetActive();   
    11. }  

           为第二个和第三个对话框也分别添加属性页类CAddendPage和CAddPage。但第二个对话框的属性页不需要重载OnSetActive函数。第三个对话框是最后一个对话框,所以不需要“下一步”按钮,而应该换成“完成”按钮,所以也需要重载OnSetActive函数设置“完成”按钮。重载后的OnSetActive如下:

    C++代码
    1. BOOL CAddPage::OnSetActive()   
    2. {   
    3.     // TODO: Add your specialized code here and/or call the base class  
    4.   
    5.     // 获得父窗口,即属性表CPropertySheet类   
    6.     CPropertySheet* psheet = (CPropertySheet*) GetParent();   
    7.     //设置属性表只有“完成”按钮   
    8.     psheet->SetFinishText(_T("完成"));   
    9.   
    10.     return CPropertyPage::OnSetActive();   
    11. }  

           上面的代码段中,字符串“完成”前加了个_T,这是因为本工程创建的时候用的默认的Unicode字符集,而如果“完成”前不加_T就是ASCII字符串。_T实际上是一个宏,工程的字符集选择为Unicode时字符串就转为Unicode字符串,选择为Muli-Byte时就转为ASCII字符串。我们可以在Solution Explorer的Addition根节点上点右键,在右键菜单上选择“Properties”,弹出工程的属性对话框,Configuration Properties->General右侧列表中的Character Set就显示选择的字符集。

           那点了第三个属性页上的“完成”按钮我们想进行某些处理的话,就重载OnWizardFinish函数,方法同OnSetActive函数。重载后的OnWizardFinish函数如下:

    C++代码
    1. BOOL CAddPage::OnWizardFinish()   
    2. {   
    3.     // TODO: Add your specialized code here and/or call the base class  
    4.   
    5.     // 提示向导完成   
    6.     MessageBox(_T("使用说明向导已阅读完!"));   
    7.   
    8.     return CPropertyPage::OnWizardFinish();   
    9. }  

            3.创建属性表类

           属性页资源和属性页类创建完以后,还不能生成向导对话框,我们还需要一个属性表类,来容纳这些属性页。

           在Solution Explorer视图中的根节点“Addition”上点右键,在右键菜单中选择Add->Class,弹出“Add Class”对话框,然后在中间区域中选择“MFC Class”,点“Add”按钮,弹出另一个类向导对话框,设置Class name为CAddSheet,Base class选择“CPropertySheet”,点“Finish”按钮,这样就属性表类就建好了。

           接下来,在新生成的AddSheet.h中包含三个属性页类的头文件:

           #include "SummandPage.h"
           #include "AddendPage.h"
           #include "AddPage.h"

           之后在AddSheet.h中添加private变量:

           CSummandPage    m_summandPage;C
           CAddendPage     m_addendPage;
           CAddPage        m_addPage;

           然后在AddSheet.cpp文件中修改CAddSheet的两个构造函数为:

    C++代码
    1. CAddSheet::CAddSheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)   
    2.     :CPropertySheet(nIDCaption, pParentWnd, iSelectPage)   
    3. {   
    4.     // 添加三个属性页到属性表   
    5.     AddPage(&m_summandPage);   
    6.     AddPage(&m_addendPage);   
    7.     AddPage(&m_addPage);   
    8. }   
    9.   
    10. CAddSheet::CAddSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)   
    11.     :CPropertySheet(pszCaption, pParentWnd, iSelectPage)   
    12. {   
    13.     // 添加三个属性页到属性表   
    14.     AddPage(&m_summandPage);   
    15.     AddPage(&m_addendPage);   
    16.     AddPage(&m_addPage);   
    17. }  

            4.显示向导对话框

            我们在加法计算器对话框上添加一个按钮,点击它就打开向导对话框。此按钮的ID设为IDC_INSTRUCT_BUTTON,Caption属性设为“使用说明”。

            按照为控件添加消息处理函数中所讲方法,为IDC_INSTRUCT_BUTTON按钮在CAdditionDlg类中添加点击消息的处理函数OnBnClickedInstructButton。然后在AdditionDlg.cpp文件中包含CAddSheet的头文件:#include "AddSheet.h"。最后修改OnBnClickedInstructButton函数如下:

    C++代码
    1. void CAdditionDlg::OnBnClickedInstructButton()   
    2. {   
    3.     // TODO: Add your control notification handler code here   
    4.   
    5.     // 创建属性表对象   
    6.     CAddSheet sheet(_T(""));   
    7.     // 设置属性对话框为向导对话框   
    8.     sheet.SetWizardMode();   
    9.     // 打开模态向导对话框   
    10.     sheet.DoModal();   
    11. }  

           到此,向导对话框就完整的创建完成了,并可以在加法计算器对话框上点“使用说明”按钮显示出来。我们来看看效果吧:

           上图只是被加数页的效果,点其上“下一步”按钮就可以继续显示后面的两个页面。

           是不是向导对话框没有以前想象的那般复杂了?大家可以发挥想象,进行更复杂的修改,实现更完善的功能。依然欢迎朋友们到鸡啄米博客来交流学习。

    **********************************************************************************************************************************************************************************

    属性页对话框包括向导对话框和一般属性页对话框两类,上一节鸡啄米讲了如何创建并显示向导对话框,本节将继续介绍一般属性页对话框的创建和显示。

           实际上,一般属性页对话框的创建和显示过程和向导对话框是很类似的。鸡啄米将上一节中的向导对话框进行少量修改,使其成为一般属性页对话框。

           一般属性页对话框的创建步骤:

           1.创建属性页对话框资源

           属性页对话框资源的创建方法同向导对话框是一样的,上一讲中的对话框资源不需进行任何修改。

           2.创建属性页类

           属性页类的创建和向导对话框的属性页类也基本一样,只是一般属性页对话框中不需要“下一步”和“完成”等按钮,所以上一讲中属性页类的OnSetActive和OnWizardFinish等重载函数可以去掉。即CSummandPage类中的OnSetActive函数、CAddPage类中的OnSetActive函数和OnWizardFinish函数可以删除或注释掉。其他部分不需作任何修改。

           3.创建属性表类

           创建属性表类的过程同向导对话框属性表类也是一样的,所以上一讲中的CAddSheet类不需修改。

           4.显示一般属性页对话框

           上一讲向导对话框的显示是在OnBnClickedInstructButton函数中实现的,其中语句sheet.SetWizardMode();旨在设置属性表为向导对话框模式,所以显示一般属性页对话框时不需调用SetWizardMode成员函数。另外,我们可以将属性页对话框的标题设为“使用说明”,在构造属性表对象时将此字符串作为构造函数的参数传入。OnBnClickedInstructButton函数修改如下:

    C++代码
    1. void CAdditionDlg::OnBnClickedInstructButton()   
    2. {   
    3.     // TODO: Add your control notification handler code here   
    4.   
    5.     // 创建属性表对象   
    6.     CAddSheet sheet(_T("使用说明"));   
    7.        
    8.     // 打开模态一般属性页对话框   
    9.     sheet.DoModal();   
    10. }  

           这样一般属性页对话框的创建和显示就讲完了,我们运行下程序,在结果对话框上点“使用说明”按钮看看效果吧:

     VS2010/MFC编程入门之十五(对话框:一般属性页对话框的创建及显示)

           再总结下,一般属性页对话框和向导对话框的创建和显示的不同包括,是否需要OnSetActive和OnWizardFinish等重载函数,是否需要调用属性表类的SetWizardMode函数设置为向导对话框模式。

    展开全文
  • Linux入门基础教程

    万次阅读 多人点赞 2018-05-29 17:52:25
    1. 1 Linux操作系统简介Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的UNIX工具软件、应用程序和网络协议。...

    1. 1      Linux操作系统简介

    Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的UNIX工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。
    1991年的10月5日,Linux创始人林纳斯·托瓦兹(Linus Torvalds)在comp.os.minix新闻组上发布消息,正式向外宣布Linux内核的诞生,1994年3月,Linux 1.0发布,代码量17万行,当时是按照完全自由免费的协议发布,随后正式采用GPL(General Public License的缩写,是一份GNU通用公共授权)协议。
    Linux具有如下优点:
    Ø       稳定、免费或者花费少
    Ø       安全性高
    Ø       多任务,多用户
    Ø       耗资源少
    Ø       由于内核小,所以它可以支持多种电子产品,如:Android手机、PDA等。

    1. 2      Linux发展趋势

    随着IT产业的不断发展,用户对网站体验要求也越来越高,而目前主流网站后端承载系统都是Linux系统,目前Android手机全部基于Linux内核研发。企业大数据、云存储、虚拟化等先进技术都是基于Linux系统。
    2010年据有关权威部门统计:将来几年内我国软件行业的从业机会十分庞大,中国每年对软件人才的需求将达到50万人左右。而对于Linux 专业人才的就业前景,更是广阔;据悉在未来5-10年内 Linux 专业人才的需求将达到 120 万+!尤其是有经验的资深的Linux工程师目前非常的缺乏,薪资也是非常诱人,平均月薪都是15-20K,能力强的薪资更高。

    所以机会对每个人都是公平的,关键是我们每个人如何去行动,选择大于努力。
     

    1. 3      Linux系统安装

    在安装Linux系统之前,先来了解windows系统结构,windows系统一般是安装在C盘系统盘,同样Linux也有类似的系统盘(/根分区),Linux通常分区为(根分区/、swap分区),Linux系统以文件的存储方式,所有的文件都是存储在某个目录下的,类似于windows的文件夹。
    对于文件系统的属性来说,windows文件系统类型一般是ntfs、fat32等,而Linux文件系统类型则为ext2、ext3、ext4等(文件系统:是操作系统用于明确磁盘或分区上的文件的方法和数据结构,文件系统由三部分组成:与文件管理有关软件、被管理文件以及实施文件管理所需数据结构。)
    安装 Linux系统是每一个初学者的第一个门槛。在这个过程中间,最大的困惑莫过于给硬盘进行分区。虽然现在各种发行版本的 Linux 已经提供了友好的图形交互界面,但是很多人还是感觉无从下手。这其中的原因主要是不清楚 Linux 的分区规定。就好比如果我们了解了windows分区的规则,系统盘C、数据盘D等,就很好分区了。
    在 Linux 中规定,每一个硬盘设备最多只能有 4个主分区(其中包含扩展分区)构成,任何一个扩展分区都要占用一个主分区号码,也就是在一个硬盘中,主分区和扩展分区一共最多是 4 个。
    下面正式来安装Linux系统,安装系统前需要准备如下软件:
    ü       VMware workstation 10.0
    ü       CentOS 5.8 x86_i386.iso
    安装图解如下:
    第一步,新建虚拟机如下图:

    第二步,选择相关选项,如下图:

    第三步选择“稍后安装操作系统”,如下图:

    第四步,选择客户机操作系统类型如下图:

    第五步,设置虚拟机硬盘大小为20G,最低不能小于5G,如下图:

    第六步,虚拟机新建完成,如下图:

    第七步,修改虚拟机内存为512M,并添加ISO镜像,如下图:

    自此,虚拟机新建完成,接下来点击“启动此虚拟机”进行Linux系统安装,Linux系统安装图解如下:
    第一步,进入安装界面,直接按Enter回车键即可。

    第二步,光盘检测,选择SKIP跳过。


    第三步,选择安装过程中的语言,初学者可以选择“简体中文”。

    第四步,选择初始化整个硬盘,清除所有数据。

    第五步,选择分区方式为“自定义分区“。


    第五步,点击“新建“-首先创建一个swap交换分区,大小为物理内存的2倍(1024M)。

    第六步,继续创建分区,选择“新建“,然后创建根分区/,如下图选择,大小为剩余所有空间即可。


    第七步,默认点击下一步,同时默认DHCP配置,时钟选择上海,去掉UTC勾,点击下一步。



    第八步,设置root密码,至少六位,点击下一步。

    第九步,系统安装包选择,这里选择“现在定制“。

    第十步,系统安装包选择,左侧选择“开发“----右侧选择”开发工具“和“开发库”,语言选择“支持中文“,其他一概不选择。


    安装完毕会提示“reboot“,直接回车即可。

    1. 4      Linux学习技巧

    初学者可以自己安装虚拟机,然后把linux常用命令例如cd、ls、chmod、useradd、vi等等多练习几十遍,把自己敲打命令的熟练程度提升上来。
    然后根据文档搭建Linux下常见的各种服务(DHCP、SAMBA、DNS、Apache、Mysql等),遇到问题后可以在google搜索,搜索的时候多看几篇文章,综合最好的文章来解决问题。
    能够熟练的搭建服务后,理解每个服务的完整配置和优化,可以拓展思维。例如LAMP,我们一般是把所有服务放在一台机器上,如果分开多台该如何部署呢?等等。
    平时多积累shell编程,可以在网上查找前辈们写的非常好的shell,自己下载下来多练习几遍,从中吸取,不断提高。
    建立一个自己的学习博客,把平时工作学习中的知识都记录在里面,这样也可以供别人来参考同时也能提高自己的编写文档及方案的能力。
    通过以上学习能够满足企业的一般应有,需要达到资深级别,还需要深入学习集群架构、负载均衡、自动化运维、运维开发等知识。最后还是一句话:多练习才是硬道理!实践出真知!

    1.   Linux系统篇

    2.1            Linux系统管理

    通过前两章的学习,我们已经能够独立安装Linux系统,已经掌握了Linux学习的技巧,那接下来,我们将系统的来了解Linux系统各目录、权限及常用命令的使用。

    2.1. 1         Linux目录初识

    通过前面的学习,我们已经能够独立安装完一个linux系统,那接下来我们来熟悉一下Linux系统里面的各个目录文件夹的大致功能:
    主要的目录树的有/、/root、/home、/usr、/bin等目录。下面是一个典型的linux目录结构如下: (附图表)

    / 根目录 
    /bin 存放必要的命令 
    /boot 存放内核以及启动所需的文件
    /dev 存放设备文件 
    /etc 存放系统配置文件 
    /home 普通用户的宿主目录,用户数据存放在其主目录中 
    /lib 存放必要的运行库 
    /mnt 存放临时的映射文件系统,通常用来挂载使用。
     /proc 存放存储进程和系统信息 
    /root 超级用户的主目录 
    /sbin 存放系统管理程序 
    /tmp 存放临时文件
    /usr 存放应用程序,命令程序文件、程序库、手册和其它文档。 
    /var 系统默认日志存放目录

    2.1. 2         Linux必备命令

    默认进入系统,我们会看到这样的字符: [root@localhost ~]#,其中#代表当前是root用户登录,如果是$表示当前为普通用户。
    我们了解linux由很多目录文件构成,那我们来学习第一个Linux命令:
    cd命令, cd  /home  ;解析:进入/home目录
    cd /root 进入/root目录 ;cd ../返回上一级目录;cd  ./当前目录;(.和..可以理解为相对路径;例如cd /hom/test ,cd加完整的路径,可以理解为绝对路径)
    接下来继续学习更多的命令:
       ls  ./ 查看当前目录所有的文件和目录。
    ls  -a 查看所有的文件,包括隐藏文件,以.开头的文件。
     
    pwd显示当前所在的目录。
    mkdir创建目录,用法mkdir  test ,命令后接目录的名称。
    rmdir 删除空目录
    rm 删除文件或者目录,用法 rm –rf  test.txt (-r表示递归,-f表示强制)。
    cp 拷贝文件,用法,cp  old.txt  /tmp/new.txt ,常用来备份;如果拷贝目录
    需要加 –r参数。
     
    mv 重命名或者移动文件或者目录,用法, mv old.txt new.txt
    touch 创建文件,用法,touch test.txt,如果文件存在,则表示修改当前文件时间。
    Useradd创建用户,用法 useradd wugk ,userdel删除用户。
    Groupadd创建组,用法 groupadd wugk1 ,groupdel删除组。
     
    find查找文件或目录,用法 find  /home  -name  “test.txt”,命令格式为:
    find 后接查找的目录,-name指定需要查找的文件名称,名称可以使用*表示所有。
    find  /home  -name  “*.txt” ;查找/home目录下,所有以.txt结尾的文件或者目录。
    vi 修改某个文件,vi有三种模式:
    命令行模式、文本输入模式、末行模式。
    默认vi打开一个文件,首先是命令行模式,然后按i进入文本输入模式,可以在文件里写入字符等等信息。
    写完后,按esc进入命令模式,然后输入:进入末行模式,例如输入:wq表示保存退出。
    如果想直接退出,不保存,可以执行:q!, q!叹号表示强制退出。
    cat 查看文件内容,用法 cat test.txt 可以看到test.txt内容
    more 查看文件内容,分页查看,cat是全部查看,如果篇幅很多,只能看到最后的篇幅。可以使用cat和more同时使用,例如: cat  test.txt |more 分页显示text内容,|符号是管道符,用于把|前的输出作为后面命令的输入。
    echo 回显,用法 echo ok,会显示ok,输入什么就打印什么。
    echo  ok  > test.txt ;把ok字符覆盖test.txt内容,>表示追加并覆盖的意思。
    >>两个大于符号,表示追加,echo ok >> test.txt,表示向test.txt文件追加OK字符,不覆盖原文件里的内容。
    初学者常见的命令就如上所示,当然还有很多深入的命令需要学习,后面的课程会讲解。

    2.1. 3         Linux用户权限管理

    在Linux操作系统中,root的权限是最高的,相当于windows的administrator,拥有最高权限,能执行任何命令和操作。在系统中,通过UID来区分用户的权限级别,UID等于0,表示此用户具有最高权限,也就是管理员。其他的用户UID依次增加,通过/etc/passwd用户密码文件可以查看到每个用户的独立的UID。
    每一个文件或者目录的权限,都包含一个用户权限、一个组的权限、其他人权限,例如下:
    标红第一个root表示该文件所有者是root用户,第二个root代表该文件的所属的组为root组,其他用户这里默认不标出。
     [root@node1 ~]# ls -l monitor_log.sh
    -rw-r--r-- 1 root root 91 May  7 20:21 monitor_log.sh
    [root@node1 ~]#
    如果我们想改变某个文件的所有者或者所属的组,可以使用命令chown
    chown  –R  test:test  monitor_log.sh即可。
    每个Linux文件具有四种访问权限:可读(r)、可写(w)、可执行(x)和无权限(-)。
    利用ls -l命令可以看到某个文件或目录的权限,它以显示数据的第一个字段为
     准。第一个字段由10个字符组成,如下:
        [root@node1 ~]# ls -l monitor_log.sh
    -rw-r--r-- 1 root root 91 May  7 20:21 monitor_log.sh
    [root@node1 ~]#
        第一位表示文件类型,-表示文件,d表示目录;后面每三位为一组。
       第一组:2-4位表示文件所有者的权限,即用户user权限,简称u
       第二组:5-7位表示文件所有者所属组成员的权限,group权限,简称g
       第三组:8-10位表示所有者所属组之外的用户的权限,other权限,简称o
    从上面这个文件,我们可以看出,monito_log.sh文件对应的权限为:
    root用户具有读和写的权限,root组具有读的权限,其他人具有读的权限。
    为了能更简单快捷的使用和熟悉权限,rwx权限可以用数字来表示,分别表示为r(4)、w(2)、x(1)。
    Monitor_log.sh权限可以表示为:644
    如果给某个文件授权,命令为chmod:chmod 777 monitor_log.sh

    2.1. 4         Linux网络配置管理

    熟悉了常用的命令和Linux权限,那接下来如何让所在的Linux系统上网呢?管理linux服务器网络有哪些命令呢?
       Linux服务器默认网卡配置文件在/etc/sysconfig/network-scripts/下,命名的名称一般为:ifcfg-eth0 ifcfg-eth1 ,eth0表示第一块网卡,eth1表示第二块网卡,依次类推。一般DELL R720标配有4块千兆网卡。
       修改网卡的IP,可以使用命令: vi /etc/sysconfig/network-scripts/ifcfg-eth0 如果是DHCP获取的IP,默认配置如下:
    # Advanced Micro Devices [AMD] 79c970 [PCnet32 LANCE]
    DEVICE=eth0
    BOOTPROTO=dhcp
    HWADDR=00:0c:29:52:c7:4e
    ONBOOT=yes
    TYPE=Ethernet
    如果是静态配置的IP,ifcfg-eth0网卡配置内容如下:
    # Advanced Micro Devices [AMD] 79c970 [PCnet32 LANCE]
    DEVICE=eth0
    BOOTPROTO=static
    HWADDR=00:0c:29:52:c7:4e
    ONBOOT=yes
    TYPE=Ethernet
    IPADDR=192.168.33.10
    NETMASK=255.255.255.0
    GATEWAY=192.168.33.1
    网卡参数详解如下:
    DEVICE=eth0   #物理设备名
    ONBOOT=yes   # [yes|no](重启网卡是否激活设备)
    BOOTPROTO=static #[none|static|bootp|dhcp](不使用协议|静态分配|BOOTP协议|DHCP协议)

    TYPE=Ethernet  #网卡类型

    IPADDR=192.168.33.10 #IP 地址
    NETMASK=255.255.255.0 #子网掩码
    GATEWAY=192.168.33.1 #网关地址
    网卡配置完毕,重启网卡,命令: /etc/init.d/network restart 即可。
    查看ip命令:ifconfig 查看当前服务器所有网卡的IP,可以单独指定,ifconfig eth0 查看eth0的IP地址。
    网卡配置完毕,如果来配置DNS,首先要知道DNS配置在哪个目录文件下,vi  /etc/resolv.conf 文件:
    在该文件里面添加如下两条:
    nameserver 202.106.0.20
    nameserver 8.8.8.8
    从上到下,分别表示主DNS,备DNS。配置完毕后,不需要重启网卡,DNS立即生效。
    可以ping www.baidu.com 看看效果:

    IP配置完毕后,我们可以通过远程工具来连接Linux服务器,常见的Linux远程连接工具有:putty、secureCRT(主流)、xshell、xmanger等工具。
    下载安装secureCRT,打开工具,然后如图配置:
    点击左上角quick connect快速连接,弹出界面,然后输入IP,用户名,端口默认是22,然后点击下方的connect连接,会提示输入密码,输入即可。

    弹出输入密码框:

    进入远程界面,与服务器真实登录一样,然后可以执行命令:

    通过这几章的学习,我们已经熟练了Linux常用命令的操作,权限网络、网络配置、远程连接等知识,那接下来我们还能做什么呢?我们已经差不多入门了,接下来就是更进一步的服务配置,Linux系统到底用来做什么呢?接下来的章节将跟大家一起来学习。  
    Linux系统的应用,我们最开始介绍的时候简单介绍过,目前大中型企业都用它来承载web网站、数据库、虚拟化平台等,那接下来我们将在Linux系统安装各种服务和软件来实现Linux真正的价值。

    2.1. 5         Linux软件包管理必备命令

    2.   Linux服务篇

    3.1            Linux服务部署

    3.1. 1         构建NTP时间服务器

    NTP服务器是用于局域网服务器时间同步使用的,可以保证局域网所有的服务器与时间服务器的时间保持一致,某些应用对时间实时性要求高的必须统一时间。
    互联网的时间服务器也有很多,例如ntpdate ntp.fudan.edu.cn 复旦大学的NTP免费提供互联网时间同步。
    NTP服务器监听端口为UDP的123,那就需要在本地防火墙开启运行客户端访问123端口,vi /etc/sysconfig/iptables添加如下规则:
    -A INPUT -m state --state NEW -m udp -p udp --dport 123 -j ACCEPT
    NTP时间服务器配置:
    yum install ntp ntpdate -y 即可!
    修改ntp.conf配置文件
    cp  /etp/ntp.conf /etc/ntp.conf.bak
    vi /etc/ntp.conf 只修改如下两行,把#号去掉即可!
    server 127.127.1.0     # local clock
    fudge  127.127.1.0 stratum 10
    以守护进程启动ntpd
    /etc/init.d/ntpd start 即可
    (注意*: ntpd启动后,客户机要等几分钟再与其进行时间同步,否则会提示“no server suitable for synchronization found”错误。)
    配置时间同步客户机
    crontab -e
    增加一行,在每天的6点10分与时间同步服务器进行同步
    10 06 * * * /usr/sbin/ntpdate ntp-server的ip >>/usr/local/logs/crontab/ntpdate.log
    备注:如果客户机没有ntpdate,可以yum –y install ntp 即可!
    以下是ntp服务器配置文件内容(局域网NTP,如果需要跟外网同步,添加外网server即可)
    driftfile /var/lib/ntp/drift
    restrict default kod nomodify notrap nopeer noquery
    restrict -6 default kod nomodify notrap nopeer noquery
    restrict 127.0.0.1
    restrict -6 ::1
    server  127.127.1.0     # local clock
    fudge   127.127.1.0 stratum 10
    includefile /etc/ntp/crypto/pw
    keys /etc/ntp/keys
    下面是参数详解:

    restrict default ignore# 关闭所有的 NTP 要求封包
    restrict 127.0.0.1# 开启内部递归网络接口 lo
    restrict 192.168.0.0 mask 255.255.255.0 nomodify#在内部子网里面的客户端可以进行网络校时,但不能修改NTP服务器的时间参数。
    server 198.123.30.132#198.123.30.132作为上级时间服务器参考
    restrict 198.123.30.132#开放server 访问我们ntp服务的权限
    driftfile /var/lib/ntp/drift在与上级时间服务器联系时所花费的时间,记录在driftfile参数后面的文件内
    broadcastdelay 0.008#广播延迟时间

     
    自此NTP服务搭建完毕,然后在所有客户端crontab里面添加如下语句:
    0  0   *  *  * /usr/sbin/ntpdate  10.0.0.155 >>/data/logs/ntp.log 2>&1

    3.1. 2         构建DHCP服务器

    DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)是一个局域网的网络协议,使用UDP协议工作,主要用途:给内部网络或网络服务供应商自动分配IP地址,DHCP有3个端口,其中UDP67和UDP68为正常的DHCP服务端口,分别作为DHCP Server和DHCP Client的服务端口。
    DHCP可以部署在服务器、交换机或者服务器,可以控制一段IP地址范围,客户机登录服务器时就可以自动获得DHCP服务器分配的IP地址和子网掩码。其中DHCP所在服务器的需要安装TCP/IP协议,需要设置静态IP地址、子网掩码、默认网关。
    正式安装DHCP服务:
    Yum  install  dhcp dhcp-devel –y 即可,然后修改DHCP /etc/dhcpd.conf配置文件内容如下:
    ddns-update-style interim;
    ignore client-updates;
    next-server  192.168.0.79;
    filename "pxelinux.0";
    allow booting;
    allow bootp; 
    subnet 192.168.0.0 netmask 255.255.255.0 {
    # --- default gateway
    option routers          192.168.0.1;
    option subnet-mask      255.255.252.0;
    #   option nis-domain       "domain.org";
    #  option domain-name "192.168.0.10";
    #   option domain-name-servers  192.168.0.11;
    #   option ntp-servers      192.168.1.1;
    #   option netbios-name-servers  192.168.1.1;
    # --- Selects point-to-point node (default is hybrid). Don't change this unless
    # -- you understand Netbios very well
    #   option netbios-node-type 2;
    range  dynamic-bootp  192.168.0.100 192.168.0.200;
    host ns {
    hardware ethernet  00:1a:a0:2b:38:81;
    fixed-address 192.168.0.101;}
    }
    参数解析如下:

    选    项解    释
      
    ddns-update-style interim|ad-hoc|none 参数用来设置DHCP服务器与DNS服务器的动态信息更新模式:interim为DNS互动更新模式,ad-hoc为特殊DNS更新模式,none为不支持动态更新模式。
    next-server ippxeclient远程安装系统,指定tftp server 地址
    filename开始启动文件的名称,应用于无盘安装,可以是tftp的相对或绝对路径  
    ignore client-updates为忽略客户端更新
    subnet-mask为客户端设定子网掩码
    option routers为客户端指定网关地址
    domain-name为客户端指明DNS名字
    domain-name-servers为客户端指明DNS服务器的IP地址
    host-name为客户端指定主机名称
    broadcast-address为客户端设定广播地址
    ntp-server为客户端设定网络时间服务器的IP地址
    time-offset为客户端设定格林威治时间的偏移时间,单位是秒

    注意如上配置,需要修改成对应服务器网段IP,然后重启DHCP服务,/etc/init.d/dhcpd restart即可。
    客户端要从这个DHCP服务器获取IP,需要做简单的设置,如果是linux需要把/etc/sysconfig/network-scritps/ifcfg-eth0里BOOTPROTO相改成dhcp即可,windows机器的话,需要修改本地连接,把它设置成自动获取IP即可。
    BOOTPROTO=dhcp

    3.1. 3         搭建Samba服务器

    Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件,由服务器及客户端程序构成,
    SMB(Server Messages Block,信息服务块)是一种在局域网上共享文件和打印机的一种通信协议,它为局域网内的不同计算机之间提供文件及打印机等资源的共享服务。
    SMB协议是客户机/服务器型协议,客户机通过该协议可以访问服务器上的共享文件系统、打印机及其他资源。通过设置“NetBIOS over TCP/IP”使得Samba不但能与局域网络主机分享资源,还能与全世界的电脑分享资源。
    安装SAMBA服务器:
    Yum install  samba –y
    安装完毕,然后做如下设置(过滤#号行、空行如下命令)
    cp /etc/samba/smb.conf /etc/samba/smb.conf.bak ;egrep -v "#|^$" /etc/samba/smb.conf.bak |grep -v "^;" >/etc/samba/smb.conf
    查看smb.conf配置文件如下:
    [global]
            workgroup = MYGROUP
            server string = Samba Server Version %v
            security = share
            passdb backend = tdbsam
            load printers = yes
            cups options = raw
     
    [temp]
         comment=Temporary file space
         path=/tmp
         read only=no
         public=yes
     
    [data]
         comment=Temporary file space
         path=/data
         read only=no
         public=yes
    根据需求修改之后重启服务:
    [root@node1 ~]# /etc/init.d/smb restart
    Shutting down SMB services:                                [FAILED]
    Shutting down NMB services:                                [FAILED]
    Starting SMB services:                                     [  OK  ]
    Starting NMB services:                                     [  OK  ]
     

    workgroup =WORKGROUP 设Samba Server 所要加入的工作组或者域。
    server string = Samba Server Version %vSamba Server 的注释,可以是任何字符串,也可以不填。宏%v表示显示Samba的版本号。
     
     
     
     
    security = user
    1.share:用户访问Samba Server不需要提供用户名和口令, 安全性能较低。
    2. user:Samba Server共享目录只能被授权的用户访问,由Samba Server负责检查账号和密码的正确性。账号和密码要在本Samba Server中建立。
    3. server:依靠其他Windows NT/2000或Samba Server来验证用户的账号和密码,是一种代理验证。此种安全模式下,系统管理员可以把所有的Windows用户和口令集中到一个NT系统上,使用Windows NT进行Samba认证, 远程服务器可以自动认证全部用户和口令,如果认证失败,Samba将使用用户级安全模式作为替代的方式。
    4. domain:域安全级别,使用主域控制器(PDC)来完成认证。
    comment = test是对该共享的描述,可以是任意字符串。
    path = /home/test共享目录路径
    browseable= yes/no 用来指定该共享是否可以浏览。
    writable = yes/nowritable用来指定该共享路径是否可写。
    available = yes/noavailable用来指定该共享资源是否可用
    admin users = admin该共享的管理者
    valid users = test允许访问该共享的用户
    invalid users = test禁止访问该共享的用户
    write list = test允许写入该共享的用户
    public = yes/nopublic用来指定该共享是否允许guest账户访问。

     
    在浏览器里面访问方式为:\\192.168.33.10 (SMB文件共享服务端IP),如何没有权限访问,需要注意防火墙和selinux设置,可以使用如下命令关闭:
    /etc/init.d/iptables stop ;sed  –i   ‘/SELINUX/s/enforcing/disabled’  /etc/sysconfig/selinux

    3.1. 4         搭建NFS服务器

    NFS 是Network File System的缩写,即网络文件系统。一种使用于分散式文件系统的协定,由Sun公司开发,于1984年向外公布。功能是通过网络让不同的机器、不同的操作系统能够彼此分享个别的数据,让应用程序在客户端通过网络访问位于服务器磁盘中的数据,是在类Unix系统间实现磁盘文件共享的一种方法。
    NFS在文件传送或信息传送过程中依赖于RPC协议。RPC,远程过程调用 (Remote Procedure Call) 是能使客户端执行其他系统中程序的一种机制。NFS本身是没有提供信息传输的协议和功能的。
    NFS应用场景,常用于高可用文件共享,多台服务器共享同样的数据,可扩展性比较差,本身高可用方案不完善,取而代之的数据量比较大的可以采用MFS、TFS、HDFS等等分布式文件系统。
    NFS安装配置:
    Yum  install nfs*  portmap  -y 如下图,安装成功即可。

    NFS安装完毕,需要创建共享目录,共享目录在/etc/exports文件里面配置,可配置参数如下:
    /data/      192.168.33.11(rw,sync,no_hide,no_all_squash)
    在配置文件中添加如上一行,然后重启Portmap,NFS服务即可,/etc/init.d/portmap restart ;/etc/init.d/nfs restart
    第一列/data/表示需要共享的目录。
    IP表示允许哪个客户端访问。
    IP后括号里的设置表示对该共享文件的权限。
    ro                      只读访问
    rw                      读写访问
    sync                    所有数据在请求时写入共享
    hide                    在NFS共享目录中不共享其子目录
    no_hide                 共享NFS目录的子目录
    all_squash              共享文件的UID和GID映射匿名用户anonymous,适合公用目录。
    no_all_squash           保留共享文件的UID和GID(默认)
    root_squash             root用户的所有请求映射成如anonymous用户一样的权限(默认)
    no_root_squas           root用户具有根目录的完全管理访问权限


    Linux客户端,如何想使用这个NFS文件系统,需要在客户端挂载,挂载命令为:
    Mount –t  nfs  192.168.33.10:/data/    /mnt 即可。如果有报错根据错误信息排查。常见问题有rpc服务没有启动、防火墙没关闭、selinux未关闭等问题。(拓展* 有兴趣的童鞋可以研究MFS(分布式文件系统)。)

    3.1. 5         搭建FTP服务器

    FTP 是文件传输协议,正是由于这种协议使得主机间可以共享文件。 FTP 使用TCP 生成一个虚拟连接用于控制信息,然后再生成一个单独的 TCP 连接用于数据传输。
    vsftpd是一款在Linux发行版中最主流的FTP服务器程序;特点是小巧轻快,安全易用;能让其自身特点得发发挥和掌握。
    目前在开源操作系统中常用的FTP服务器程序主要有vsftpd、ProFTPD、PureFTPd和wuftpd等,这么多FTP服务器程序,关键在于自己熟练哪一个就使用哪一个。今天我们来研究一下VSFTPD简单安装及使用。安装命令: yum  install vsftpd*  -y

    修改配置文件如下:
    #vsftpd config 2014 by wugk
    anonymous_enable=NO    //禁止匿名用户访问
    local_enable=YES  //允许本地用户登录FTP
    write_enable=YES   //运行用户在FTP目录有写入的权限
    local_umask=022   //设置本地用户的文件生成掩码为022,默认是077
    dirmessage_enable=YES //激活目录信息,当远程用户更改目录时,将出现提示信息
    xferlog_enable=YES   //启用上传和下载日志功能
    connect_from_port_20=YES  //启用FTP数据端口的连接请求
    xferlog_std_format=YES  //是否使用标准的ftpd xferlog日志文件格式
    listen=YES  //使vsftpd处于独立启动监听端口模式
    pam_service_name=vsftpd //设置PAM认证服务配置文件名称,文件存放在/etc/pam.d/目录
    userlist_enable=YES   //用户列表中的用户是否允许登录FTP服务器,默认是不允许
    tcp_wrappers=YES    //使用tcp_wrqppers作为主机访问控制方式
     
    1)    第一种方法就是使用系统用户登录FTP,但是也是比较危险的,先测试系统用户登录FTP,在Linux系统上创建useradd  test 用户,并为其设置名,然后在xp客户端打开我的电脑资源里面访问 ftp://192.168.33.10,输入用户名和密码即可访问,进行创建和删除操作。
    2)    第二种方法比较安全,配置相对复杂一点,就是使用vsftpd虚拟用户登录FTP服务器进行常见的操作。
    Ø       首先安装FTP 虚拟用户需要用到的软件及认证模块
    yum install pam* db4* --skip-broken –y
    创建并生成vsftpd数据库文件vi /etc/vsftpd/ftpusers.txt,内容如下:
    第一行为FTP虚拟用户,登录用户名,第二行为密码,第三行为用户名,依次类推。
    wugk
    1
    wugk1
    1
    Ø       生成数据库文件命令:
    db_load -T -t hash -f /etc/vsftpd/ftpusers.txt /etc/vsftpd/vsftpd_login.db
    chmod 700 /etc/vsftpd/vsftpd_login.db
    Ø       配置PAM验证文件:
    在配置文件vi /etc/pam.d/vsftpd 行首加入如下两行认证语句:(如果是32位,lib64需改成lib,如果RedHat,加入的语句不一样,需注意)
    auth    sufficient      /lib64/security/pam_userdb.so     db=/etc/vsftpd/vsftpd_login
    account sufficient      /lib64/security/pam_userdb.so      db=/etc/vsftpd/vsftpd_login
    Ø       创建vsftpd映射本地用户:
    所有的FTP虚拟用户需要使用一个系统用户,这个系统用户不需要密码,也不需要登录。主要用来做虚拟用户映射使用。
    useradd  –d /home/ftpuser –s /sbin/nologin ftpuser
    Ø       修改完整版配置文件内容如下:
    anonymous_enable=NO
    local_enable=YES
    write_enable=YES
    local_umask=022
    dirmessage_enable=YES
    xferlog_enable=YES
    connect_from_port_20=YES
    xferlog_file=/var/log/vsftpd.log
    xferlog_std_format=YES
    ascii_upload_enable=YES
    ascii_download_enable=YES
    listen=YES
     
    guest_enable=YES
    guest_username=ftpuser
    pam_service_name=vsftpd
    user_config_dir=/etc/vsftpd/vsftpd_user_conf
    virtual_use_local_privs=YES
     
       保存重启,/etc/init.d/vsftpd restart 即可使用虚拟用户登录,这时候所有的虚拟用户共同使用/home/ftpuser目录上传下载,如果想使用自己独立的目录,可以在/etc/vsftpd/vsftpd_user_conf目录创建各自的配置文件,如给wugk创建独立的配置文件:
    vi /etc/vsftpd/vsftpd_user_conf/wugk ,内容如下,建立自己的FTP目录。
    local_root=/home/ftpsite/wugk
    write_enable=YES
    anon_world_readable_only=YES
    anon_upload_enable=YES
    anon_mkdir_write_enable=YES
    anon_other_write_enable=YES
     重启,使用客户端登录FTP,测试即可。关于FTP讲解就到此,windows还可以使用Server-U来搭建FTP服务器端,有兴趣的童鞋可以研究一下。
    Ø       FTP主被动模式
    FTP主动模式:客户端从一个任意的非特权端口N(N>1024)连接到FTP服务器的port 21命令端口。然后客户端开始监听端口N+1,并发送FTP命令“port N+1”到FTP服务器。接着服务器会从它自己的数据端口(20)连接到客户端指定的数据端口(N+1)。
    FTP被动模式:客户端从一个任意的非特权端口N(N>1024)连接到FTP服务器的port 21命令端口。然后客户端开始监听端口N+1,同时客户端提交 PASV命令。服务器会开启一个任意的非特权端口(P >1024),并发送PORT P命令给客户端。然后客户端发起从本地端口N+1到服务器的端口P的连接用来传送数据。

    展开全文
  • Python入门教程完整版(懂中文就能学会)

    万次阅读 多人点赞 2020-05-21 16:43:37
    今天本宝宝给大家带来了干货,Python入门教程完整版,...4-13天内容:为Python基础教程14-15 天内容:为飞机大战项目演练 第一阶段(1-3天): 该阶段首先通过介绍不同领域的三种操作系统,操作系统的发展简史以及...
  • Kafka教程(一)Kafka入门教程

    万次阅读 多人点赞 2016-04-21 17:41:16
    Message Queue 消息传送系统提供传送服务。消息传送依赖于大量支持组件,这些组件负责处理连接服务、消息的路由和传送、持久性、安全性以及日志记录。消息服务器可以使用一个或多个代理实例。 JMS(Java Messaging ...
  • oracle入门教程

    万次阅读 多人点赞 2019-07-11 14:14:02
    推荐一个Oracle入门学习教程 点击下面链接进入自学网站 学习网站:http://www.51zxw.net/study.asp?vip=16229363 点击图片箭头所指按钮——请点击进入学习 在下面方框里面搜索Oracle 第一个搜索结果就是小姐姐...
  • 【设计模式】策略模式

    万次阅读 多人点赞 2020-01-23 19:51:16
    博主声明: 转载请在开头附加本文链接及作者信息,并标记为转载。本文由博主威威喵原创,请多支持与指教。 ... 晚上的时候,抽了点时间看了一下设计模式相关书籍,毕竟有些东西还是得重温一下的,脑子不灵光,记住...
  • Python基础教程,Python入门教程(非常详细)

    万次阅读 多人点赞 2019-06-25 13:26:47
    第1章 Python编程基础 1.编程语言是什么 2.编译型语言和解释型语言 3.Python是什么 4.Python具有哪些特点(优点和缺点) 5.学Python,不需要有编程基础! 6.学Python能干什么 7.Python 2.x和Python 3.x,初学...
  • 2015年最新Android基础入门教程目录(完结版)

    万次阅读 多人点赞 2015-12-21 20:44:26
    2015年最新Android基础入门教程目录(完结版) 前言: 关于《2015年最新Android基础入门教程目录》终于在今天落下了帷幕,全套教程 共148节已编写完毕,附上目录,关于教程的由来,笔者的情况和自学心得,资源分享 ...
  • 最新Android基础入门教程目录(完结版)

    万次阅读 多人点赞 2018-03-29 19:17:14
    第一章:环境搭建与开发相关(已完结 10/10)https://blog.csdn.net/coder_pig/article/details/50000773Android基础入门教程——1.1 背景相关与系统架构分析Android基础入门教程——1.2 开发环境搭建Android基础入门...
  • 最好的MATLAB入门教程(没有之一!)

    万次阅读 多人点赞 2018-11-21 23:48:21
     这个是MathWorks公司官方提供的MATLAB入门教程,简洁明了!!!非常适合初学者,这是我迄今为止见过的最好的入门教程,没有之一!!!  如果你是初学者,我建议你花两个小时看完,...
  • 爬虫入门教程 —— 1

    万次阅读 多人点赞 2019-03-13 10:11:24
    爬虫入门教程 -1 很想做一些爬虫的基础性的教程,来与大家共同分享我的一些小经验, 我将以我认为的方式为大家讲解网络爬虫,如果你没有编程基础,对网络爬虫有兴趣,开始可能稍微有一些小难度,不过我希望能给你...
  • 简谱入门基础教程.pdf

    2020-07-30 23:32:11
    简谱入门基础教程.pdf
  • 这里推荐这门python编程入门基础教程,适合零基础的同学学习! python软件工程师都学什么? 自学Python,看视频学的更快、更透彻一些,给你个课程大纲! 阶段一:Python开发基础 Python全栈开发与人工智能之Python开发...
  • C++入门教程:C++基础教程,含进阶

    千次阅读 2017-01-09 15:25:57
    C++入门教程:C++基础教程,含进阶http://c.biancheng.net/cpp/biancheng/cpp/rumen/
  • iOS开发入门教程

    万次阅读 2016-07-22 21:52:18
    iOS开发入门教程,从创建项目到运行项目,包括OC基础,调试,模拟器设置等相关知识。 程序发轻狂,代码阑珊,苹果开发安卓狂!——写给狂热的编程爱好者们 写在前面的话 学习iOS应用程序开发已有一段...
  • 《Python基础教程》---值得读几遍的Python入门

    万次阅读 多人点赞 2018-08-04 12:21:36
    《Python基础教程》看了三遍。第一遍囫囵吞枣、尝试写代码;第二遍重温,同步看《Python学习手册》、《Python Cookbook》,部分细节(如正则表达式)对照另两本书一起看,敲代码;第三遍仔细看了一遍,花了一个多月...
  • 基于AD的入门教程

    2020-03-24 11:46:05
    感觉入门教程还是很重要的,万丈高楼平地起。为了方便新手入门,就把2层板,柔性板,多层板的入门经验写下来,毕竟经验分享出来才是经验。当然这是简单的入门教程,电路设计包罗万象,高阶的进修还需要自己的不断...
  • 计算机基础教程(一)

    万次阅读 多人点赞 2019-07-30 11:12:01
    《大学计算机基础教程PDF》下载链接 链接:https://pan.baidu.com/s/1PGsvh1oRD1euWUedEXNl8w 密码:zt4x 推荐先看下面的两本: 计算机是怎样跑起来的 程序是怎样跑起来的 这两本百度云连接,CSDN审核不通过,...
1 2 3 4 5 ... 20
收藏数 578,876
精华内容 231,550
关键字:

入门教程