Skip to content

Latest commit

 

History

History
444 lines (359 loc) · 14.3 KB

File metadata and controls

444 lines (359 loc) · 14.3 KB

ccsocket ABI Reference

本文档由 ccsocket.h / ccsocket.c 源码自动生成。 描述 ccsocket 库的全部公开 ABI(Application Binary Interface),包括类型、常量、枚举、宏与导出函数。


1. 编译宏 / 类型定义

1.1 基本类型

宏 / typedef 值 (Unix) 值 (Windows) 说明
ccsocket_t int intptr_t 套接字句柄类型
INVALID_SOCKET (~0) 系统定义 无效套接字常量
cciovec_buf_t void* char* IO 向量缓冲区指针
cciovec_len_t size_t uint32_t IO 向量长度类型

1.2 长度常量

#define MAX_ADDRLEN  255
#define MAX_ERRORLEN 255

1.3 ccsocket_iovec_t — IO 向量结构

typedef struct ccsocket_iovec {
#if _WIN32               // Windows: len 在前
    cciovec_len_t  len;
    cciovec_buf_t  buf;
#else                    // Unix:    buf 在前
    cciovec_buf_t  buf;
    cciovec_len_t  len;
#endif
} ccsocket_iovec_t;

⚠️ 跨平台时字段顺序不同,不可将原始结构跨平台序列化。

1.4 IO 向量宏

ccsocket_init_iov(iov, count)        // 清零 iov 数组
ccsocket_get_iov_len(iov, idx)       // 读取长度
ccsocket_set_iov_len(iov, idx, slen) // 设置长度
ccsocket_get_iov_buf(iov, idx)       // 读取缓冲区指针
ccsocket_set_iov_buf(iov, idx, sbuf) // 设置缓冲区指针

2. 枚举类型

2.1 ccsocket_flags_t — 套接字标志

typedef enum {
    CC_NOFLAG   = 0,  // 无特殊标志
    CC_CLOEXEC  = 1,  // close-on-exec
    CC_NONBLOCK = 2,  // 非阻塞
} ccsocket_flags_t;

标志可按位组合:CC_CLOEXEC | CC_NONBLOCK 等价于 3

2.2 ccsocket_stcode_t — send/recv 操作返回码

typedef enum {
    CC_OPCODE_ERROR       = -1,  // 不可恢复错误,需关闭套接字
    CC_OPCODE_OK          =  0,  // 操作成功
    CC_OPCODE_WAIT        =  1,  // 需等待(非阻塞模式下缓冲区空/满)
    CC_OPCODE_WANT_REVENT =  2,  // 期望可读事件
    CC_OPCODE_WANT_WEVENT =  3,  // 期望可写事件
} ccsocket_stcode_t;

2.3 ccsocket_family_t — 地址族

typedef enum {
    CC_FAMILY_INVALID = -1,  // 无效 / 未知
    CC_UNIX  = 0,            // AF_UNIX  Unix 域套接字
    CC_INET4 = 1,            // AF_INET   IPv4
    CC_INET6 = 2,            // AF_INET6  IPv6
} ccsocket_family_t;

2.4 ccsocket_protocol_t — 传输协议

typedef enum {
    CC_PROTOCOL_INVALID = -1,  // 无效协议
    CC_TCP   = 1,              // SOCK_STREAM  + IPPROTO_TCP
    CC_UDP   = 2,              // SOCK_DGRAM   + IPPROTO_UDP
    CC_ICMP  = 3,              // SOCK_RAW     + IPPROTO_ICMP (IPv6 → IPPROTO_ICMPV6)
} ccsocket_protocol_t;

2.5 ccsocket_conn_state_t — 连接状态

typedef enum {
    CC_CONNERROR  = -1,  // 连接失败
    CC_CONNECTED  =  0,  // 已连接
    CC_CONNECTING =  1,  // 连接中(非阻塞模式)
} ccsocket_conn_state_t;

2.6 ccsocket_sendf_state_t — sendfile 状态

typedef enum {
    CC_SENDERROR = -1,  // 不可恢复错误
    CC_SENDALL   =  0,  // 文件发送完毕
    CC_SENDWAIT  =  1,  // 发送缓冲区满,需等待
} ccsocket_sendf_state_t;

2.7 ccaddrinfo_t — 地址信息链表节点

typedef struct ccaddrinfo {
    char              address[65];  // 点分/冒号分隔 IP 字符串
    ccsocket_family_t af;           // 地址族
    struct ccaddrinfo *next;        // 下一节点
} ccaddrinfo_t;

3. API 便捷宏

这些宏是对底层 ABI 函数的包装,用户在头文件可见。

// 创建套接字
#define ccsocket(domain, protocol) \
    ccsocket2((domain), (protocol), CC_NOFLAG)

#define ccsocket1(domain, protocol, flags) \
    ccsocket2((domain), (protocol), (ccsocket_flags_t)(flags))

// 接受连接
#define ccsocket_accept(s, flags) \
    ccsocket_accept2((s), NULL, NULL, (ccsocket_flags_t)(flags))

#define ccsocket_accept1(s, paddr, pport, flags) \
    ccsocket_accept2((s), (paddr), (pport), (ccsocket_flags_t)(flags))

// socketpair
#define ccsocketpair(fds, flags) \
    ccsocketpair1((fds), (ccsocket_flags_t)(flags))

// 发送
#define ccsocket_send(s, buf, bsize, wsizep) \
    ccsocket_send1((s), (buf), (bsize), (wsizep), 0)

#define ccsocket_sendv(s, iov, iovcnt, wsizep) \
    ccsocket_sendv1((s), (iov), (iovcnt), (wsizep), 0)

4. 导出函数 (ABI)

4.1 创建与关闭

ccsocket_close

int ccsocket_close(ccsocket_t s);
  • 说明:关闭套接字。
  • 返回值:0 成功,非 0 失败。

ccsocket2

ccsocket_t ccsocket2(ccsocket_family_t domain, ccsocket_protocol_t proto, ccsocket_flags_t flags);
  • 说明:创建套接字(底层 ABI)。
  • 参数
    • domainCC_UNIX / CC_INET4 / CC_INET6
    • protoCC_TCP / CC_UDP / CC_ICMP
    • flagsCC_NOFLAG / CC_CLOEXEC / CC_NONBLOCK
  • IPv6 ICMPdomain=CC_INET6 + proto=CC_ICMP 时使用 IPPROTO_ICMPV6(58)替代 IPPROTO_ICMP(1),系统未定义该常量时降级为 -1
  • 返回值:有效套接字句柄,失败返回 INVALID_SOCKET

ccsocketpair1

bool ccsocketpair1(ccsocket_t sv[2], ccsocket_flags_t flags);
  • 说明:创建一对已连接的流式套接字(类似 socketpair)。
  • 参数
    • sv:输出,长度为 2 的套接字数组。
    • flags:套接字标志。
  • Windows 实现:通过 TCP 本地回环模拟。
  • 返回值true 成功,false 失败。

4.2 服务端

ccsocket_listen

bool ccsocket_listen(ccsocket_t s, const char *addr, uint16_t port);
  • 说明:绑定地址并监听(独占模式)。
  • 参数
    • s:由 ccsocket2 创建的套接字。
    • addr:IP 地址字符串(如 "0.0.0.0"),Unix 域为路径。
    • port:端口号,Unix 域传 0。
  • 行为:优先使用 SO_EXCLUSIVEADDRUSE(Windows)或 SO_EXCLBIND(Solaris),其他平台降级为 SO_REUSEADDR
  • 返回值true 成功。

ccsocket_listen1

bool ccsocket_listen1(ccsocket_t s, const char *addr, uint16_t port);
  • 说明:绑定地址并监听(负载均衡模式,允许多进程/线程共享端口)。
  • 平台支持:Linux 3.9+, DragonFlyBSD 3.6+, FreeBSD 12+, Solaris 11.4+, AIX 7.2.5.0+。
  • 错误处理:失败时 errno / WSAGetLastError() 保留底层原始错误(如 EADDRINUSE),不会被覆盖为 EINVAL
  • 返回值true 成功。

ccsocket_accept2

ccsocket_t ccsocket_accept2(ccsocket_t s, OPTIONAL char *addr, OPTIONAL uint16_t *port, ccsocket_flags_t flags);
  • 说明:从监听套接字接受一个客户端连接(底层 ABI)。
  • 参数
    • s:监听套接字。
    • addr:可选,输出客户端 IP / Unix 路径,缓冲区 ≥ MAX_ADDRLEN
    • port:可选,输出客户端端口。
    • flags:新套接字的标志。
  • 非阻塞行为:无连接且未出错时返回 (ccsocket_t)0(Unix)或 0
  • 返回值:新客户端套接字,失败返回 INVALID_SOCKET,需等待返回 0

4.3 客户端

ccsocket_connect

bool ccsocket_connect(ccsocket_t s, const char *addr, uint16_t port);
  • 说明:连接到指定地址和端口。
  • 参数
    • s:由 ccsocket2 创建的套接字。
    • addr:目标 IP / Unix 路径。
    • port:目标端口。
  • 返回值true 成功。

ccsocket_is_connected

ccsocket_conn_state_t ccsocket_is_connected(ccsocket_t s);
  • 说明:查询套接字连接状态。
  • 返回值CC_CONNECTED / CC_CONNECTING / CC_CONNERROR

4.4 数据收发

ccsocket_send1

ccsocket_stcode_t ccsocket_send1(ccsocket_t s, const void *buf, size_t bsize, OPTIONAL int *wsize, int flags);
  • 说明:发送数据(底层 ABI)。
  • 返回值
    • CC_OPCODE_OK — 发送完成,*wsize 为写入字节数。
    • CC_OPCODE_WAIT — 非阻塞模式下发送缓冲区满。
    • CC_OPCODE_ERROR — 不可恢复错误。

ccsocket_sendv1

ccsocket_stcode_t ccsocket_sendv1(ccsocket_t s, ccsocket_iovec_t *iov, int iovcnt, OPTIONAL int *wsize, int flags);
  • 说明:发送聚集 IO 向量数据。
  • 参数
    • iov:IO 向量数组。
    • iovcnt:向量条目数。
  • 返回值:同 ccsocket_send1

ccsocket_recv

ccsocket_stcode_t ccsocket_recv(ccsocket_t s, char *buf, size_t bsize, OPTIONAL int *rsize);
  • 说明:接收数据到连续缓冲区。
  • 返回值
    • CC_OPCODE_OK — 接收成功,*rsize 为读取字节数。
    • CC_OPCODE_WAIT — 非阻塞模式下无数据可读。
    • CC_OPCODE_ERROR — 不可恢复错误。

ccsocket_recv1

ccsocket_stcode_t ccsocket_recv1(ccsocket_t s, ccsocket_iovec_t *iov, int iovcnt, OPTIONAL int *rsize);
  • 说明:接收数据到 IO 向量数组。
  • 返回值:同 ccsocket_recv

ccsocket_peek

ccsocket_stcode_t ccsocket_peek(ccsocket_t s, char *buf, size_t bsize, OPTIONAL int *rsize);
  • 说明:窥视套接字接收缓冲区数据(不移除)。
  • 返回值:同 ccsocket_recv

ccsocket_sendfile

ccsocket_sendf_state_t ccsocket_sendfile(ccsocket_t s, int fd);
  • 说明:将文件描述符内容发送到套接字。
  • 平台行为
    • macOS/FreeBSD/BSD → sendfile() 系统调用(零拷贝)。
    • Linux/Solaris → sendfile() 系统调用(零拷贝)。
    • AIX → send_file() 系统调用。
    • 其他(含 Windows)→ read() + ccsocket_send() 回退。
  • 注意:非一次性调用;需在循环中调用直到返回 CC_SENDALL 或错误。
  • 返回值
    • CC_SENDALL — 文件发送完毕。
    • CC_SENDWAIT — 需等待(发送缓冲区满)。
    • CC_SENDERROR— 不可恢复错误。

4.5 地址与名称查询

ccsocket_get_peername

bool ccsocket_get_peername(ccsocket_t s, char *addr, uint16_t *port);
  • 说明:获取对端(远程)地址和端口。

ccsocket_get_sockname

bool ccsocket_get_sockname(ccsocket_t s, char *addr, uint16_t *port);
  • 说明:获取本端(本地)地址和端口。

ccsocket_get_family

ccsocket_family_t ccsocket_get_family(ccsocket_t s);
  • 说明:返回套接字地址族(CC_INET4 / CC_INET6 / CC_UNIX / CC_FAMILY_INVALID)。

ccsocket_get_version

ccsocket_family_t ccsocket_get_version(const char *addr);
  • 说明:解析字符串判断地址族。
  • 返回值
    • CC_INET4 — IPv4 地址(如 "1.1.1.1")。
    • CC_INET6 — IPv6 地址(如 "::1")。
    • CC_UNIX — Unix 域套接字路径(仅在非 Windows 下,通过 stat+ S_ISSOCK 检测)。
    • CC_FAMILY_INVALIDNULL、非 IP 非套接字路径,设 errno = EINVAL

ccsocket_get_error

void ccsocket_get_error(ccsocket_t s, char buf[MAX_ERRORLEN]);
  • 说明:获取最后一个错误的可读描述。

4.6 套接字选项

连接设置

bool ccsocket_set_nodelay(ccsocket_t s, bool on);      // TCP_NODELAY (禁用 Nagle)
bool ccsocket_set_keepalive(ccsocket_t s, bool on);    // SO_KEEPALIVE
bool ccsocket_enable_accept_defer(ccsocket_t s);       // TCP_DEFER_ACCEPT / SO_ACCEPTFILTER

地址复用

bool ccsocket_set_reuseaddr(ccsocket_t s, bool on);    // SO_REUSEADDR
bool ccsocket_set_reuseport(ccsocket_t s, bool on);    // SO_REUSEPORT (需内核支持)

IO 行为

bool ccsocket_set_nonblock(ccsocket_t s, bool on);     // 非阻塞模式
bool ccsocket_set_cloexec(ccsocket_t s, bool on);      // close-on-exec
bool ccsocket_set_rcvtimeout(ccsocket_t s, int timeout); // SO_RCVTIMEO (毫秒)
bool ccsocket_set_sndtimeout(ccsocket_t s, int timeout); // SO_SNDTIMEO (毫秒)

4.7 DNS 解析

ccsocket_getaddrinfo

bool ccsocket_getaddrinfo(const char *domain, ccaddrinfo_t **addrlist);
  • 说明:解析域名,返回去重后的地址链表。
  • 参数
    • domain:域名或 IP 字符串;为 NULL 时返回 false 并设 errno = EINVAL
    • addrlist:输出,地址链表头指针。调用者需用 ccsocket_freeaddrinfo 释放。
  • 返回值true 成功,false 失败(可通过 errnoccsocket_get_error 获取原因)。

ccsocket_freeaddrinfo

void ccsocket_freeaddrinfo(ccaddrinfo_t *addrlist);
  • 说明:释放 ccsocket_getaddrinfo 返回的地址链表。

5. 内部辅助函数(非 ABI,仅供参考)

函数 签名 说明
ccsizeof int ccsizeof(const struct sockaddr_storage*) 根据 ss_family 返回 sockaddr 实际大小
ccsocket2addr bool ccsocket2addr(const struct sockaddr_storage*, char*, uint16_t*) 从 sockaddr 提取 IP 和端口
ccsocket_wrap_ip_and_port bool ccsocket_wrap_ip_and_port(...) 将 IP 字符串 + 端口填充到 sockaddr
_ccsocket_set_flags int _ccsocket_set_flags(ccsocket_t, ccsocket_flags_t, bool) 设置/清除套接字标志
_ccsocket_get_family int _ccsocket_get_family(ccsocket_t, struct sockaddr_storage*) 获取套接字地址族
ccsocket_listen_internal bool ccsocket_listen_internal(ccsocket_t, const char*, uint16_t) 内部 bind + listen
ccsocket_recv_internal ccsocket_stcode_t ccsocket_recv_internal(...) 内部 recv

6. 平台兼容性矩阵

功能 Linux macOS FreeBSD Windows Solaris AIX
TCP
UDP
ICMP
Unix Domain 1
socketpair 2
sendfile (零拷贝) 3
accept4 4 4
SO_REUSEPORT 5
TCP_DEFER_ACCEPT
SO_ACCEPTFILTER

Footnotes

  1. Windows 10 RS2+ (1703) 原生支持,更早版本不支持。

  2. Windows 通过 TCP 回环模拟。

  3. Windows 回退为 read()+send()

  4. macOS/FreeBSD 不支持 accept4,回退到 accept()+fcntl 2

  5. FreeBSD 12+ 使用 SO_REUSEPORT_LB