您的位置:首页 > 理论基础 > 计算机网络

Unix网络编程第三版源码编译

2016-12-02 18:04 393 查看
环境:

$ cat /etc/issue

Ubuntu 12.04.1 LTS \n \l

$ cat /proc/version

Linux version 3.2.0-48-generic (buildd@komainu) (gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) ) #74-Ubuntu SMP Thu Jun 6 19:43:26 UTC 2013

$ uname -a

Linux ubuntu-server 3.2.0-48-generic #74-Ubuntu SMP Thu Jun 6 19:43:26 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

下载:

$ git clone https://github.com/maxliaops/Unix-Network-Programming.git
配置:

$ cd Unix-Network-Programming/

$ chmod 755 configure

$ ./configure

主要的工作是检查系统是否有源码编译所依赖的各种资源(系统版本是否匹配、编译器、库文件、头文件以及结构体定义等等)

checking build system type... x86_64-unknown-linux-gnu

checking host system type... x86_64-unknown-linux-gnu

checking for gcc... gcc

checking for C compiler default output... a.out

checking whether the C compiler works... yes

checking whether we are cross compiling... no

checking for suffix of executables...

checking for suffix of object files... o

checking whether we are using the GNU C compiler... yes

checking whether gcc accepts -g... yes

checking for gcc option to accept ANSI C... none needed

checking for ranlib... ranlib

checking for pthread_create in -lpthread... yes

checking for t_open in -lnsl... no

checking for library containing socket... none required

checking for /usr/local/bind/lib/libbind.a... no

checking for /home/liaops/libbind.a... no

checking for /home/liaops/libresolv.a... no

checking for res_init in -lresolv... no

checking for t_open in -lxti... no

checking for /home/liaops/libunp.a... no

checking for /home/liaops/libunpxti.a... no

checking how to run the C preprocessor... gcc -E

checking for egrep... grep -E

checking for ANSI C header files... yes

checking for sys/types.h... yes

checking for sys/socket.h... yes

checking for sys/time.h... yes

checking for time.h... yes

checking for netinet/in.h... yes

checking for arpa/inet.h... yes

checking for errno.h... yes

checking for fcntl.h... yes

checking for netdb.h... yes

checking for signal.h... yes

checking for stdio.h... yes

checking for stdlib.h... yes

checking for string.h... yes

checking for sys/stat.h... yes

checking for sys/uio.h... yes

checking for unistd.h... yes

checking for sys/wait.h... yes

checking for sys/un.h... yes

checking for sys/param.h... yes

checking for sys/select.h... yes

checking for sys/sysctl.h... yes

checking for poll.h... yes

checking for sys/event.h... no

checking for strings.h... yes

checking for sys/ioctl.h... yes

checking for sys/filio.h... no

checking for sys/sockio.h... no

checking for pthread.h... yes

checking for net/if_dl.h... no

checking for xti.h... no

checking for xti_inet.h... no

checking for netconfig.h... no

checking for netdir.h... no

checking for stropts.h... yes

checking whether time.h and sys/time.h may both be included... yes

checking if uint8_t defined... yes

checking if int16_t defined... yes

checking if uint16_t defined... yes

checking if int32_t defined... yes

checking if uint32_t defined... yes

checking if size_t defined... yes

checking if ssize_t defined... yes

checking if socklen_t defined... yes

checking if sa_family_t defined... yes

checking if t_scalar_t defined... no

checking if t_uscalar_t defined... yes

checking for struct sockaddr.sa_len... no

checking for struct sockaddr_storage... yes

checking for struct sockaddr_storage.ss_family... yes

checking for struct msghdr.msg_control... yes

checking for struct ifreq.ifr_mtu... yes

checking for getaddrinfo function prototype in netdb.h... yes

checking for getnameinfo function prototype in netdb.h... yes

checking for gethostname function prototype in unistd.h... yes

checking for getrusage function prototype in sys/resource.h... yes

checking for hstrerror function prototype in netdb.h... yes

checking for if_nametoindex function prototype in net/if.h... yes

checking for inet_aton function prototype in arpa/inet.h... yes

checking for inet_pton function prototype in arpa/inet.h... yes

checking for pselect function prototype in sys/select.h... yes

checking for snprintf function prototype in stdio.h... yes

checking for sockatmark function prototype in sys/socket.h... yes

checking for struct addrinfo... yes

checking for struct if_nameindex... yes

checking for struct sockaddr_dl... no

checking for struct timespec... yes

checking for /dev/tcp... no

checking for /dev/xti/tcp... no

checking for /dev/streams/xtiso/tcp... no

checking for bzero... yes

checking for getaddrinfo... yes

checking for gethostname... yes

checking for gethostbyname2... yes

checking for gethostbyname_r... yes

checking for getnameinfo... yes

checking for hstrerror... yes

checking for if_nametoindex... yes

checking for inet_aton... yes

checking for inet_pton... yes

checking for inet6_rth_init... yes

checking for kqueue... no

checking for kevent... no

checking for mkstemp... yes

checking for poll... yes

checking for pselect... yes

checking for snprintf... yes

checking for sockatmark... yes

checking for vsnprintf... yes

checking for IPv4 support... yes

checking for IPv6 support... yes

checking for Unix domain sockets... yes

checking for multicast support... yes

checking for -I/home/liaops/doc/unp2ev1/src/include... no

configure: creating ./config.status

config.status: creating Makefile

config.status: creating Make.defines

config.status: creating config.h

编译库:

编译所有例程都需要用到的基础库

$ cd lib

$ make

得到静态库文件:libudp.a

查看符号表 (主要是想看一下这个库的各个源文件调用了哪些Linux系统调用)

$ nm -g libunp.a

从中可以发现以下几个文件比较重要,主要是对常用的API进行了一层包装。

wrapsock.o:     对套接字socket的包装

    accept

    bind

    connect

    err_quit

    err_sys

    getenv

    getpeername

    getsockname

    getsockopt

    inet6_rth_add

    inet6_rth_getaddr

    inet6_rth_init

    inet6_rth_reverse

    inet6_rth_segments

    inet6_rth_space

    listen

    poll

    recv

    recvfrom

    recvmsg

    select

    send

    sendmsg

    sendto

    setsockopt

    shutdown

    sockatmark

    socket

    socketpair

    strtol

wrapstdio.o:    对标准IO库中文件相关函数的包装

    fclose

    fdopen

    ferror

    fgets

    fopen

    fputs

wrappthread.o:  对线程库pthread的包装

    pthread_cond_broadcast

    pthread_cond_signal

    pthread_cond_timedwait

    pthread_cond_wait

    pthread_create

    pthread_detach

    pthread_join

    pthread_key_create

    pthread_kill

    pthread_mutex_init

    pthread_mutex_lock

    pthread_mutex_unlock

    pthread_mutexattr_init

    pthread_mutexattr_setpshared

    pthread_once

    pthread_setspecific

wrapunix.o:     对其他常用Linux/Unix系统调用的包装

    __strdup

    calloc

    close

    dup2

    err_quit

    err_sys

    fcntl

    fork

    gettimeofday

    ioctl

    malloc

    mkstemp

    mmap

    open

    pipe

    read

    sigaddset

    sigdelset

    sigemptyset

    sigfillset

    sigismember

    sigpending

    sigprocmask

    sysconf

    sysctl

    unlink

    wait

    waitpid

    write

问题:为什么要对这些API接口进行包装,是否多此一举?

继续编译基本库

$ cd ../libfree/

$ make

gcc -I../lib -g -O2 -D_REENTRANT -Wall -c -o in_cksum.o in_cksum.c

gcc -I../lib -g -O2 -D_REENTRANT -Wall -c -o inet_ntop.o inet_ntop.c

inet_ntop.c: In function ‘inet_ntop’:

inet_ntop.c:61: error: argument ‘size’ doesn’t match prototype

/usr/include/arpa/inet.h:65: error: prototype declaration

make: *** [inet_ntop.o] Error 1

出现错误!

Fix:

inet_ntop.c第61行 size_t size ->改成 socklen_t size)

再次编译

$ make

gcc -I../lib -g -O2 -D_REENTRANT -Wall -c -o inet_ntop.o inet_ntop.c

gcc -I../lib -g -O2 -D_REENTRANT -Wall -c -o inet_pton.o inet_pton.c

ar rv ../libunp.a in_cksum.o inet_ntop.o inet_pton.o

a - in_cksum.o

a - inet_ntop.o

a - inet_pton.o

ranlib ../libunp.a

貌似这次编译的内容并到了libunp.a中,没有生成新的库文件。

$ cd ../libgai

$ make

ar rv ../libunp.a

ranlib ../libunp.a

拷贝生成的库文件到系统库目录

$ cd ..

$ sudo cp libunp.a /usr/lib

$ sudo cp libunp.a /usr/lib32

以后编译代码的时候加上-lunp链接我们的库。

修改unp.h并将其和config.h拷贝到/usr/include中

编译并测试一个基本的客户端例程

$ cd intro/

$ make daytimetcpcli

gcc -I../lib -g -O2 -D_REENTRANT -Wall -c -o daytimetcpcli.o daytimetcpcli.c

gcc -I../lib -g -O2 -D_REENTRANT -Wall -o daytimetcpcli daytimetcpcli.o ../libunp.a -lpthread

编译成功后,在当前目录会生成可执行镜像daytimetcpcli

运行daytimetcpcli

$ ./daytimetcpcli

usage: a.out <IPaddress>

$ ./daytimetcpcli 127.0.0.1

connect error: Connection refused

Fix:

开启daytime服务

$ make daytimetcpsrv

gcc -I../lib -g -O2 -D_REENTRANT -Wall -c -o daytimetcpsrv.o daytimetcpsrv.c

gcc -I../lib -g -O2 -D_REENTRANT -Wall -o daytimetcpsrv daytimetcpsrv.o ../libunp.a -lpthread

sudo ./daytimetcpsrv &

再次运行daytimetcpcli

$ ./daytimetcpcli 127.0.0.1

Mon Mar 3 22:47:35 2014

转自:http://blog.csdn.net/u011435712/article/details/41648837

本文用的Unix网络编程源码是第三版,不同版本的源码可能会有不同的错误,还有不同的操作系统也会有不同的错误,本文基于fedora
20 64位操作系统,不过一般都不是满大的问题,多改两下就好了。

配置:

cd Unix-Network-Programming/

./configure      //若无法执行,可以用chmod更改权限

主要的工作是检查系统是否有源码编译所依赖的各种资源(系统版本是否匹配、编译器、库文件、头文件以及结构体定义等等)

编译库:

编译所有例程都需要用到的基础库

cd lib

make

得到静态库文件:libudp.a

继续编译基本库

$ cd ../libfree/

$ make

gcc -I../lib -g -O2 -D_REENTRANT -Wall   -c -o in_cksum.o in_cksum.c
gcc -I../lib -g -O2 -D_REENTRANT -Wall   -c -o inet_ntop.o inet_ntop.c
inet_ntop.c: In function ‘inet_ntop’: 
inet_ntop.c:60:9: error: argument ‘size’ doesn’t match prototype
  size_t size;
         ^
In file included from inet_ntop.c:27:0:

/usr/include/arpa/inet.h:64:20: error: prototype declaration
 extern const char *inet_ntop (int __af, const void *__restrict __cp,
                    ^
make: *** [inet_ntop.o] Error 1

出现错误!仔细查看发是在 inet_ntop方法中的参数size的类型,与声明在 /usr/include/arpa/inet.h中的inet_ntop()中的size参数类型不一致导致

使用 vim /usr/include/arpa/inet.h 命令查看inet_ntop函数的声明,发现其size的类型为socklen_t,所以将原size类型改为socklen_t就可以了,然后还要修改inet_ntop4()和inet_ntop()6函数的参数类型,然后就大功告成。

再次编译

$ make

gcc -I../lib -g -O2 -D_REENTRANT -Wall -c -o inet_ntop.o inet_ntop.c

gcc -I../lib -g -O2 -D_REENTRANT -Wall -c -o inet_pton.o inet_pton.c

ar rv ../libunp.a in_cksum.o inet_ntop.o inet_pton.o

a - in_cksum.o

a - inet_ntop.o

a - inet_pton.o

ranlib ../libunp.a

貌似这次编译的内容并到了libunp.a中,没有生成新的库文件。

$ cd ../libgai

$ make

ar rv ../libunp.a

ranlib ../libunp.a

拷贝生成的库文件到系统库目录

$ cd ..

$ sudo cp libunp.a /usr/lib

$ sudo cp libunp.a /usr/lib32

将unp.h中  #include "../config.h"
修改为#include "config.h",并将其和config.h拷贝到/usr/include中,

然后编译源代码

cd ./intro  

gcc daytimetcpcli.c -o daytimetcpcli -lunp  

跟普通的编译不一样的是要在最后加上刚才那个链接库,-l参数加上刚才那个libunp.a去掉lib和后面的.a。最后得到参数-lunp。

还可以参考:https://zhidao.baidu.com/question/1541318318288252827.html
http://blog.csdn.net/mengxiang_tianji/article/details/51119048
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: