Socket 是網路程式設計的核心介面。本筆記系統整理 Socket 建立、綁定、監聽、連接、資料收發、地址轉換、選項設定、關閉等全生命週期 API,涵蓋 IPv4、IPv6、Unix 域、UDP/TCP,適合網路程式開發者隨時查閱。
int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 建立 bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)); // 綁定 listen(sockfd, backlog); // 監聽 int connfd = accept(sockfd, (struct sockaddr*)&cli, &len); // 接受連接 // 收發資料 recv(connfd, buf, len, flags); send(connfd, buf, len, flags); close(connfd); close(sockfd); // 關閉
| API | 用途 | 關鍵參數/返回值 |
|---|---|---|
socket(domain, type, proto) | 建立 Socket | domain: AF_INET/AF_INET6/AF_UNIX; type: SOCK_STREAM/SOCK_DGRAM; 返回 fd 或 -1 |
bind(sockfd, addr, len) | 綁定地址 | addr: sockaddr_in/sockaddr_in6/sockaddr_un; 返回 0/-1 |
listen(sockfd, backlog) | 轉為被動監聽 | backlog: 等待佇列長度 |
accept(sockfd, addr, len) | 接受連接 | 返回新連接 fd,阻塞直到有連接 |
connect(sockfd, addr, len) | 發起連接 (客戶端) | 阻塞直到連接成功/失敗 |
send/recv | TCP 資料收發 | flags: MSG_DONTWAIT 等; 返回實際字節數/0(對端關閉)/-1 |
sendto/recvfrom | UDP 資料收發 | 需每次指定目標/來源地址 |
shutdown(sockfd, how) | 關閉單向 | how: SHUT_RD/SHUT_WR/SHUT_RDWR |
getsockopt/setsockopt | 選項獲取/設定 | level: SOL_SOCKET/IPPROTO_TCP; optname: SO_REUSEADDR/TCP_NODELAY 等 |
// IPv4
struct sockaddr_in {
sa_family_t sin_family; // AF_INET
in_port_t sin_port; // 網路序端口
struct in_addr sin_addr; // s_addr: 網路序 IP
char sin_zero[8]; // 填充對齊
};
// IPv6
struct sockaddr_in6 {
sa_family_t sin6_family; // AF_INET6
in_port_t sin6_port;
uint32_t sin6_flowinfo;
struct in6_addr sin6_addr; // 16 bytes
uint32_t sin6_scope_id;
};
// Unix 域
struct sockaddr_un {
sa_family_t sun_family; // AF_UNIX
char sun_path[108]; // 路徑,以\0結尾
};
#include <arpa/inet.h> uint16_t htons(uint16_t host); // 主機序→網路序 (16位) uint32_t htonl(uint32_t host); // 主機序→網路序 (32位) uint16_t ntohs(uint16_t net); // 網路序→主機序 uint32_t ntohl(uint32_t net); // 字串↔二進制 IP int inet_pton(int af, const char *src, void *dst); // 字串→結構 const char *inet_ntop(int af, const void *src, char *dst, size_t size); // 結構→字串
#include <netdb.h>
int getaddrinfo(const char *host, const char *service,
const struct addrinfo *hints, struct addrinfo **res);
// 返回鏈表 res,包含 sockaddr 可直接用於 socket/bind/connect
void freeaddrinfo(struct addrinfo *res);
int socketpair(int domain, int type, int protocol, int sv[2]); // 建立一對已連接的 Unix 域 socket,用於父子進程/無親緣進程高效通訊
#include <sys/sendfile.h> ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count); // 零拷貝:核心空間直接在兩個 fd 間傳輸,避免用戶態拷貝
熟練掌握 Socket API 全景,是構建高效、穩健網路服務的基石。