UNIX 网络编程笔记-CH3:套接字编程简介

IPv4套接字地址结构

struct in_addr {
    in_addr_t s_addr;  
};

struct sockaddr_in {
    uint8_t             sin_len;        /* length of structure (16) bytes */
    sa_family_t         sin_family;     /* AF_INET */
    in_port_t           sin_port;       /* 16-bit TCP/UDP port, network byte order(big-endian) */
    struct in_addr      sin_addr;       /* 4-byte IPv4 address, network byte */

    char                   sin_zero[8]; /* unused */   
}

共16字节,编程时需要设置的一般就是sin_family, sin_port, sin_addr这三个字段。因为这是IPv4对应的套接字地址结构体所以有sin_family=AF_INET,后两个字段需要通过换转函数把本机字节序的值变为网络字节序(大端)。

通用套接字地址结构

套接字接口除了处理IPv4对应的套接字地址结构外,还需要支持其他各种套接字地址结构,如IPv4,Unix套接字等。所以在void*指针类型尚未出现前,定义了一个通用套接字结构体:

struct sockaddr {
    uint8_t           sa_len;
    sa_family_t       sa_family;
    char              sa_data[14];
};

相应的各套接字函数的地址参数都使用了struct sockaddr*类型的参数,使用时把各个类型的套接字地址结构体指针都强制转换为struct sockaddr*,这样单个套接字函数可以根据sa_family和长度复制数据并对不同类型的套接字分别处理了。如bind函数:

int bind(int sockfd, struct sockaddr* addr, socklen_t len);

 套接字地址参数值传递

从进程向内核传递套接字地址的函数有:

1. bind(int fd, struct sockaddr* addr, int addrlen)

2. connect(int fd, struct sockaddr* addr, int addrlen)

3. sendto

从内核到进程传递套接字地址的函数有:

1. accept(int fd, struct sockaddr* addr, int* len),len在调用时向内核指明地址结构大小,在返回时指明实际存储的数据大小

2. recvfrom

3. getsockname

4. getpeername

字节序转换函数

uint16_t htons(uint16_t host16bitvalue);
uint32_t htonl(uint32_t host32bitvalue);
uint16_t ntohs(uint16_t net16bitvalue);
uint32_t ntohl(uint32_t net32bitvalue);

h-host, n-network, s-short, l-long int==>int

地址字符与数值转换

IPv4地址可以使用点分十进制也可以使用直接的数值(网络序),书中推荐使用下面两个函数进行转化

#include <arpa/inet.h>

int inet_pton(int family, const char* str, void* addrptr);

const char* inet_ntop(int family, const void* addptr, char* strbuf, size_t len);

对于IPv4来说addrptr应该取sockaddr_in.sin_addr的地址,常用的类似功能的函数有

#include <arpa/inet.h>

int inet_aton(const char*strptr, struct in_addr *addrptr);

in_addr_t inet_addr(const char* strptr);

char* inet_ntoa(struct in_addr inaddr);
原文地址:https://www.cnblogs.com/lailailai/p/4338529.html