unp.h环境搭建以及在WSL中的使用

选到了想上的网络编程课,用的书是非常著名的Unix Networking Programming Volume 1(Edition 3),那么实验自然是用书上的实验了。书上的实验基本上都引用了unp.h的头文件,这个头文件是这本书编写的一种All in one的环境,并且在某些结构体未定义的情况下补充定义结构体等功能,该环境需要手动安装和配置,因此记录一下在配置过程,以及过程中出现的问题和解决办法。

系统环境

WSL2,发行版为Ubuntu 20.04LTS,其他WSL发行版以及原版Linux应该都差不多(未经过考证)

VSCode和插件Remote WSL

build-essential,使用apt安装

配置过程

  1. 下载unp库的源码,下载地址

  2. 解压并进入文件夹,按照README的步骤执行以下命令

    ./configure
    
    cd lib/
    make
    
    cd ../libfree/
    make
    

    libfree/中make的时候可能会遇到size_t的报错

    解决办法是将libfree/inet_ntop.c的第60行size_t改为socklen_t即可

    在此过程中还可能会遇到一些warning,可能是因为使用的gcc-9和比较高版本的内核,和这个库有一点不太兼容,只要没有error就可以执行

  3. make完成回到主目录下,发现已经编译好静态库libunp.a,将其复制到/usr/lib/usr/lib64两个目录下,再将config.hkey/unp.h复制到/usr/include/unp目录下(这里我新建了unp的目录为了方便管理,也可以直接放在/usr/include目录下),并将unp.h中的#include "../config.h"改为#include "config.h"(只要你的unp.h能找到config.h就好了)

  4. 开始使用书上的例子作为测试

    #include "unp.h"
    
    int main(int argc, char **argv) {
        int sockfd, n;
        char recvline[MAXLINE + 1];
        struct sockaddr_in servaddr;
    
        if (argc != 2) {
            err_quit("usage: a.out <IPaddress>");
        }
    
        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
            err_sys("socket error");
        }
    
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port   = htons(13);
        if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {
            err_quit("inet_pton error for %s", argv[1]);
        }
    
        if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0) {
            err_sys("connect error");
        }
    
        while ((n = read(sockfd, recvline, MAXLINE)) > 0) {
            recvline[n] = 0;
            if (fputs(recvline, stdout) == EOF) {
                err_sys("fputs error");
            }
        }
        if (n < 0) {
            err_sys("read error");
        }
    
        exit(0);
    }
    

    执行以下编译命令

    gcc cli.c -o cli -lunp
    

    可能会出现以下报错

    1. in_pktinfo重复定义

      发现是in_pktinfo的结构体重复定义了,具体的定义位置是在/usr/include/x86_64-linux-gnu/bits/in.h第157行,比较两者的定义可以发现,其中的变量名称都是相同的,那么直接替换应该没有问题,但是直接注释看上去又不太好(其实应该没问题),所以参考unp.h中的其他代码风格,在config.h中定义了一个宏#define HAVE_STRUCT_IN_PKTINFO 1,然后将unp.h中的结构体定义用#ifndef框起来,如下图

      再次编译就没有这个错误了

    2. err_syserr_print没有定义

      这是因为该函数是单独写出来的,需要下载其他文件,为了避免节外生枝,笔者直接采用printf()exit()来显示并退出

至此,unp.h环境搭建完毕,并且直接使用VSCode的Remote WSL到连虚拟机,C语言的插件也能识别到unp库的东西

原文地址:https://www.cnblogs.com/BadCodeBuilder/p/13870485.html