unix高级网络编程

转载 2013年12月05日 21:49:49

  最近在学习《UNIX环境高级编程》(Advanced Programming in the UNIX Environment, 简称APUE,以下使用简称)。该书的作者是W.Richard.Stevens,国际知名的UNIX和网络专家。我看的是该书的第一版,尤晋元翻译的。网上有的评论该书翻译的比较差劲,有的说还行。我个人觉得,这本书的翻译还可以。并且,如果本身就有一定的UNIX/Linux基础的话,读起来应该不是很吃力。同时我也下了该书的第二版(英文版),有什么看不懂的地方,再对照英文版看一下,辅助理解。
   这里要谈到的一个问题就是该书中的源代码编译的问题。此书中差不多每个历程中,都会有这样一行源码:
#include "ourhdr.h"
  
在第二版中改为:
#include "apue.h"

    这个头文件是作者把把每个例程中常用的标准头文件,一些常用的出错处理函数(err_**()之类的函数)和一些常用的宏定义给整理在一个头文件中。这个可以省去在每个例程中录入较多的重复代码,这样可以减少每个例程的长度。但是,这样就给读者带来了不少麻烦。因为我们还要去搞明白如和把这个头文件编译,然后做成库文件,添加到我们的系统中。特别读于初学者,本来满怀信心的,结果在编译第一个程序的时候就出现了问题。我也没有搞明白如何把 "ourhdr.h"静态的编译到系统中。

    不过,不明白如何使用"ourhdr.h"这个头文件,并不会影响我们学习APUE,也不会影响我们编译和运行每一个例程。其实,简单的想一下,如果一个 C程序要能顺利的编译和运行,除了我们要语法正确等方面外,最根本的是要保证我们程序中所调用的函数以及宏等等都要有完整的来源,也就是必须包含所有调用函数和宏所在的头文件。对于一个具体的源程序,如果我们正确的包含了头文件,那么剩下的就是程序本生语法方面应该注意的事项。

    如何确定系统调用函数包含在那个头文件中呢?这在Unix/Linux系统下并非一件难事。Unix/Linux下命令man可以帮助我们找到。man命令不仅可以帮助我们查找一般命令的用法,同时提供不同层次的帮助诸如系统调用或者管理员级别的命令等等(譬如FreeBSD6.1中,man 1是用户专用手册,man 2是系统调用,man 3是库函数查询等等)。

    下面我们就以APUE书中程序1-1 (实现ls命令部分功能)为例,来说明如何将书中的程序改编成全部使用标准头文件的程序。其中,操作系统用的是FreeBSD6.1,经过相应的修改可以在书中所说的几个Unix系统及Linux系统中运行,我也曾在Debian Linux下成功编译和运行该程序。书中1-1.c的原始代码如下:

#include <sys/types.h>
#include <dirent.h>
#include "ourhdr.h"

int
main(int argc, char *argv[])
{
    DIR                *dp;
    struct dirent    *dirp;

    if (argc != 2)
        err_quit("usage: ls directory_name");

    if ((dp = opendir(argv[1])) == NULL)
        err_sys("can't open %s", argv[1]);
    while ((dirp = readdir(dp)) != NULL)
        printf("%s\n", dirp->d_name);

    closedir(dp);
    exit(0);
}

    从书后面的附录中可以看到"ourhdr.h"的内容比较多,包含了比较多的常用头文件,一些宏定义和一些常用函数和出错函数的定义。其实,对于每一个具体的程序,我们只需要找到该程序中用到的头文件即可。

    该1-1.c中所用到的系统函数调用有:opnedir(),readdir(),printf(),closedir()和exit()。
其中,对于常用的函数prinft()和exit(),它们所在的头文件一般都知道,分别是<stdio.h>和<stdlib.h>。而对于
opnedir (),readdir()和closedir(),我们可以通过man opendir,man readdir,man closedir得到这三个关于目录操作的函数所在的头文件都是:<sys/types.h>和<dirent.h>。这两个头文件在源程序中也已经列出。

    其次,1-1.c中还用到了作者自定义的两个函数:err_quit()和err_sys()。这两个函数主要使用来进行出错处理的。当然,使用这两个函数对错误信息的处理是比较完善的。但是,作为我们学习来讲,了解程序的核心功能是首要的,我们可以将出错处理简化一点,即当遇到错误的时候,我们只简单的使用printf()函数来提示一下有错误发生。当然,用printf()来进行出错处理并不是一种很合理的方法,而且往往我们看不到更关键的错误信息,但对于我们仅仅作为学习来用还是可以接受的。毕竟我们要理解的核心部分是程序的功能实现,出错处理在于其次。

   通过以上的说明,我们可以将1-1.c修改为如下内容:

#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
    DIR *dp;
    struct dirent *dirp;
   
    if(argc != 2)
    {
        printf("You need input the directory name.\n");
        exit(1);  
    }
   
    if((dp = opendir(argv[1])) == NULL)
    {
        printf("cannot open %s\n", argv[1]);
        exit(1);   

    }

    while ((dirp = readdir(dp)) != NULL)
        printf("%s\n", dirp->d_name);


    closedir(dp);

    exit(0);
}

    这样修改后的程序已经与作者的头文件"ourhdr.h"没有关系,可以单独的进行编译。我使用的是root用户,执行命令:

# gcc 1-1.c  //生成目标文件a.out
或者
# gcc -o 1-1 1-1.c  //生成目标文件1-1

    没有任何错误和警告,说明编译成功。这时我们执行生成的目标文件:

# ./a.out /home
或者
# ./1-1 /home

    则会列出/home路径下的所有文件,包括目录(.)和(..)。

    通过这样的方法,基本上我们可以将该书中所有的例程修改成不包含"ourhdr.h"的程序。这样,我们就可以单独的编译每一个例程,而不用顾及作者所给的杂凑的头文件。同时这种比较笨的方法,反而有利于帮助我们了解不同系统调用所对应的头文件,对于学习来说,这应该是一件好事。

 

相关文章推荐

UNIX网络编程------高级I/O函数(十四)

UNIX网络编程------高级IO函数 1、  套接字的I/O操作上设置超时操作; 1)  使用信号处理函数alarm,不过这样会涉及到信号处理函数的问题,同时还有可能会引起程序中其他alarm函数...

Unix网络编程(六)高级I/O技术之复用技术 select

本文将讨论网络编程中的高级I/O复用技术,将从下面几个方面进行展开: a. 什么是复用技术呢? b. 什么情况下需要使用复用技术呢? c. I/O的复用技术的工作原理是什么? d. select, p...

Unix网络编程代码 第14章 高级I/O函数

第14章 高级I/O函数 14.2 套接字超时 14.2.1 使用SIGALRM 为连接设置超时 #include /* sockaddr_in{} and other Internet d...

《UNIX网络编程 卷1》 笔记补充内容: 高级轮询技术epoll

epoll是Linux提供的高级轮询技术,《UNIX网络编程 卷1》成书时还没有这种技术。它的效率要比单独使用poll函数高很多,非常适合监听大量的描述符,许多高性能的服务器都使用epoll。下面是e...

UNIX网络编程笔记(10)—高级IO函数

高级IO函数

Unix网络编程 高级IO套接字设置超时

我们知道,对于一个套接字的读写(read/write)操作默认是阻塞的,如果当前套接字还不可读/写,那么这个操作会一直阻塞下去,这样对于一个需要高性能的服务器来说,是不能接受的。所以,我们可以在进行读...

《UNIX网络编程 卷1》 笔记: 高级I/O函数

本节我们关注称为“高级I/O”的各个函数和技术。 首先是在I/O操作上设置超时。在涉及套接字的I/O操作上设置超时的方法有以下3种; 1. 调用alarm函数,在定时时间超时产生SIGALRM信号...

UNIX环境高级编程-读书笔记-网络编程(四)

网络通信 总结:1.不管是UDP还是TCP通信,基本的过程都是,首先建立链接,然后发送消息,然后对方接受消息。 2.网络通信的模式,的书写方法都是固定的,不管是UDP还是TCP。写法固定。 3.网...

UNIX环境高级编程-读书笔记-网络编程(一)

一.两种网络模型ISO/OSI 网络拓扑模型 7层应用层 表示层 会话层 传输层 网络层 数据链路层 物理层TCP/TP 网络模型 4层 应用层 用户态 ——————————————...

UNIX环境高级编程-读书笔记-网络编程(三)

UDP 通信过程采用的是c/s的软件架构 客户端 1.socket —-> 2.sendto ——>3.close详解: 1.socket:创建通信套接字 函数: int socket()...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)