Linux网络编程基础API

yubo-guan / 2024-01-25 / 原文

目录
  • socket地址API
    • 主机字节序和网络字节序
  • 创建socket
  • 命名socket
  • 监听socket
  • 接收连接
  • 发起连接
  • 关闭连接
  • 数据读写
  • 带外标记
  • 地址信息函数
  • socket选项
  • 网络信息API


socket地址API

主机字节序和网络字节序

在 Linux 系统中,主机字节序(Host Byte Order)和网络字节序(Network Byte Order)是两个重要的概念。

  • 主机字节序是指 CPU 直接处理数据时使用的字节序。在 x86 架构的 Linux 系统中,主机字节序通常是小端字节序(Little Endian),即最低有效字节(Least Significant Byte)位于最低内存地址。
  • 网络字节序是指在网络通信中使用的字节序。在 TCP/IP 协议中,网络字节序通常是大端字节序(Big Endian),即最高有效字节(Most Significant Byte)位于最低内存地址。

在进行网络编程时,经常需要在主机字节序和网络字节序之间进行转换。例如,在发送数据时,需要将主机字节序转换为网络字节序;在接收数据时,需要将网络字节序转换为主机字节序。
在 Linux 系统中,可以使用htonl()htons()ntohl()ntohs()等函数进行字节序转换。这些函数的命名规则如下:

  • h表示主机(Host)。
  • n表示网络(Network)。
  • l表示长整型(Long)。
  • s表示短整型(Short)。

例如,htonl()函数将一个 32 位的整数从主机字节序转换为网络字节序,ntohl()函数将一个 32 位的整数从网络字节序转换为主机字节序。

下面是一个简单的示例,展示了如何在 Linux 中进行字节序转换:

#include <iostream>
#include <arpa/inet.h>

int main() {
    // 定义一个32位整数
    uint32_t host = 0x12345678;

    // 将主机字节序转换为网络字节序
    uint32_t network = htonl(host);

    // 将网络字节序转换为主机字节序
    uint32_t host2 = ntohl(network);

    // 打印结果
    std::cout << "主机字节序:" << std::hex << host << std::endl;
    std::cout << "网络字节序:" << std::hex << network << std::endl;
    std::cout << "转换后的主机字节序:" << std::hex << host2 << std::endl;

    return 0;
}

在上面的示例中,我们定义了一个 32 位的整数host整数,然后使用htonl()函数将其转换为网络字节序,并使用ntohl()函数将其转换回主机字节序。最后,我们打印出转换前后的结果。

判断机器字节序

#include <iostream>
#include <endian.h>

// 判断机器字节序函数
bool isLittleEndian() {
    return __BYTE_ORDER__ == LITTLE_ENDIAN;
}

void isLittleEndian02() {
    union {
        short value;
        char union_bytes[sizeof(short)];
    } test;
    test.value = 0x0102;
    if (test.union_bytes[0] == 1 && test.union_bytes[1] == 2) {
        std::cout << "这台机器是大端字节序(big endian)" << std::endl;
    } else if (test.union_bytes[0] == 2 && test.union_bytes[1] == 1) {
        std::cout << "这台机器是小端字节序(little endian)" << std::endl;
    } else {
        std::cout << "unknown..." << std::endl;
    }
}

int main() {
    if (isLittleEndian()) {
        std::cout << "这台机器是小端字节序(little endian)" << std::endl;
    } else {
        std::cout << "这台机器是大端字节序(big endian)" << std::endl;
    }

    isLittleEndian02();

    return 0;
}

/*
这台机器是小端字节序(little endian)
这台机器是小端字节序(little endian)
*/

函数isLittleEndian(),它使用__BYTE_ORDER__和__LITTLE_ENDIAN__宏来判断机器的字节序。如果__BYTE_ORDER__等于__LITTLE_ENDIAN__,则说明机器是小端字节序;否则,机器是大端字节序。

函数isLittleEndian02(),在这个代码中,使用了一个union(联合体)来同时访问一个 16 位整数的不同字节。在这个union中,value成员是一个 16 位整数,而union_bytes成员是一个字符数组,长度为sizeof(short),即 2。
首先,将 0x0102 赋值给value成员。然后,检查union_bytes成员中的第一个和第二个字节的值。如果第一个字节的值为 1,第二个字节的值为 2,那么这台机器是大端字节序;如果第一个字节的值为 2,第二个字节的值为 1,那么这台机器是小端字节序;否则,字节序是未知的。


创建socket


命名socket


监听socket


接收连接


发起连接


关闭连接


数据读写


带外标记


地址信息函数


socket选项


网络信息API