socket 套接字函数
原型:
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
参数含义:
1)domin(协议族 / 地址族)——“在哪一层地址上工作”
宏 | 说明 | 常见用途 |
---|---|---|
AF_INET / PF_INET | IPv4 | TCP/UDP over IPv4 |
AF_INET6 / PF_INET6 | IPv6 | TCP/UDP over IPv6 |
AF_UNIX / PF_UNIX | 本地套接字(aka AF_LOCAL ) | 本机进程间高速通信 |
AF_NETLINK | 与内核 netlink 对话 | 路由、防火墙、udev 等 |
AF_PACKET | 裸链路层 | 自己组装以太帧(抓包、发裸包) |
2)type(语义类型)——“给我什么样的行为”
宏 | 说明 | 对应传输层 | |
---|---|---|---|
SOCK_STREAM | 可靠、面向连接、字节流 | TCP | |
SOCK_DGRAM | 不可靠、无连接、数据报 | UDP | |
SOCK_RAW | 绕过内核传输层,自己写 IP 头 | ICMP、自定义 IP 协议 | |
SOCK_SEQPACKET | 可靠、面向连接、但保留报文边界 | SCTP 或 unix 域 | |
`SOCK_DGRAM | SOCK_NONBLOCK` | 原子非阻塞 UDP | 需要内核 2.6.27+ |
`SOCK_STREAM | SOCK_CLOEXEC` | 自动 close-on-exec | 避免泄露给子进程 |
3)protocol——“更精确地挑协议”
宏 | 值 | 含义 |
---|---|---|
IPPROTO_TCP | 6 | TCP |
IPPROTO_UDP | 17 | UDP |
IPPROTO_ICMP | 1 | ICMP(需 SOCK_RAW) |
IPPROTO_SCTP | 132 | SCTP |
IPPROTO_RAW | 255 | 原始 IP,自己填首部 |
4)最常用的“复制粘贴”组合
int tcp4 = socket(AF_INET, SOCK_STREAM, 0); // IPv4 TCPint udp4 = socket(AF_INET, SOCK_DGRAM, 0); // IPv4 UDPint tcp6 = socket(AF_INET6, SOCK_STREAM, 0); // IPv6 TCPint udp6 = socket(AF_INET6, SOCK_DGRAM, 0); // IPv6 UDPint icmp = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); // IPv4 原始 ICMPint unix = socket(AF_UNIX, SOCK_STREAM, 0); // 本地字节流
5)返回值与错误
成功:非负整数 —— 后续 read/write/bind/listen/connect/accept/setsockopt/close 都用它。
失败:-1,查看 errno
常见: EACCES
权限不足(RAW 需 CAP_NET_RAW) EMFILE
进程 fd 耗尽 ENFILE
系统 fd 耗尽 EPROTONOSUPPORT
内核没编译该协议 ENOMEM
内存不足
一句话速记 domain 选“地址类型”,type 选“行为”,protocol 选“具体协议”,0 交给内核猜。