套接字编程基础

IPv4套接字地址结构

/* <netinet/in.h> */
struct in_addr {
    in_addr_t      s_addr;  /* 32-bit IPv4 address */
                            /* network byte ordered */
}

struct sockaddr_in {
    uint8_t        sin_len;     /* length of structure (16-bit) */
    sa_family_t    sin_family;  /* AF_INET (16-bit) */
    in_port_t      sin_port;    /* 16-bit TCP or UDP port number */
                                /* network byte ordered */
    struct in_addr sin_addr; 
    char           sin_zero[8]; /* unused */
}

通用套接字地址结构

/* <sys/socket.h> */
struct sockaddr {
    uint8_t        sa_len;      /* length of structure (16-bit) */
    sa_family_t    sa_family;   /* address family: AF_xxx value */
    char           sa_data[14]; /* protocol-specific address */
}

IPv6套接字地址结构

/* netinet/in.h */
struct in6_addr {
    uint8_t s6_addr[16];           /* 128-bit IPv6 address */
}

struct sockaddr_in6 {
    uint8_t        sin6_len;       /* length of this struct (28) */
    sa_family_t    sin6_family;    /* AF_INET6 */
    in_port_t      sin6_port;      /* transport layer port */
    uint32_t       sin6_flowinfo;  /* flow information, undefined */
    struct in6_addr  sin6_addr;    /* IPv6 address */
    uint32_t       sin6_scope_id; 
}

新的通用套接字地址结构

struct sockaddr_storage {
    uint8_t        ss_len;
    sa_family_t    ss_family;
    
    
}

字节序(大小端)

非常喜欢UNP对于大小端字节序的解释,清晰明了。原文是这样描述的:

考虑一个16位整数,它由2个字节组成,内存中存储这两个字节有两种方法:一种是将低序字节存储在起始地址,这称为小端(litttle-endian)字节序;另一种方法是将高序字节存储在起始地址,这称为大端(big-endian)字节序。

网络字节序默认是大端字节序。

字节序转换函数

#include <netinet/in.h>

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

地址转换函数

#include <arpa/inet.h>

/* 仅适用于IPv4 */
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);

/* 对于IPv4地址和IPv6地址都适用 */
int inet_pton(int family, const char *strptr, void *addrptr);
const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len);

基本套接字函数

#include <sys/socket.h>

/* 返回:若成功则为非负描述符,若出错则为-1 */
int socket(int family, int type, int protocol); 
int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);
int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);
int listen(int sockfd, int backlog);
int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);

/* 返回与套接字关联的本地协议地址 */
int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen);
/* 返回与套接字管理的外地协议地址 */
int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen);

#include <unistd.h>
pid_t fork(void);
int close(int sockfd);

参考
《UNIX网络编程 - 卷1:套接字联网API (第3版)》

posted @ 2020-08-08 16:16  hustluotao  阅读(157)  评论(0编辑  收藏  举报