socket系统调用的参数涵义
在 Linux 中,socket()
系统调用用于创建一个新的网络套接字(socket),它是网络通信的基础。其函数原型如下:
c
复制
#include <sys/types.h> #include <sys/socket.h> int socket(int domain, int type, int protocol);
参数详解
1. domain
(协议族/地址族)
指定套接字使用的协议族(Address Family),决定了通信的地址类型和协议类型。常见选项:
值 | 宏定义 | 说明 |
---|---|---|
IPv4 | AF_INET | 使用 IPv4 地址(如 192.168.1.1 )。 |
IPv6 | AF_INET6 | 使用 IPv6 地址(如 2001:db8::1 )。 |
本地通信 | AF_UNIX /AF_LOCAL | 用于本地进程间通信(IPC),基于文件路径(如 /tmp/mysocket )。 |
原始协议 | AF_PACKET | 允许直接访问网络层数据包(如构造自定义协议头)。 |
示例:
c
复制
int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 创建 IPv4 TCP 套接字
2. type
(套接字类型)
指定套接字的通信语义(数据传输方式)。常见类型:
值 | 宏定义 | 说明 |
---|---|---|
流式套接字 | SOCK_STREAM | 面向连接、可靠的双向字节流(如 TCP)。 |
数据报套接字 | SOCK_DGRAM | 无连接、不可靠的固定长度报文(如 UDP)。 |
原始套接字 | SOCK_RAW | 直接访问网络层协议(如 ICMP、自定义 IP 包)。 |
顺序包套接字 | SOCK_SEQPACKET | 类似 SOCK_STREAM ,但保留报文边界(如 SCTP)。 |
示例:
c
复制
int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 创建 UDP 套接字
3. protocol
(具体协议)
指定套接字使用的具体协议,通常设为 0
(由内核根据 domain
和 type
自动选择)。常见选项:
协议 | 值 | 适用场景 |
---|---|---|
TCP | IPPROTO_TCP | 与 SOCK_STREAM 配合使用(AF_INET + SOCK_STREAM 默认选 TCP)。 |
UDP | IPPROTO_UDP | 与 SOCK_DGRAM 配合使用(AF_INET + SOCK_DGRAM 默认选 UDP)。 |
ICMP | IPPROTO_ICMP | 用于 Ping 或 Traceroute(需配合 SOCK_RAW )。 |
自定义 | 其他协议号 | 如 IPPROTO_SCTP (SCTP 协议)。 |
示例:
c
复制
int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); // 创建 ICMP 原始套接字
常见组合示例
用途 | domain | type | protocol |
---|---|---|---|
TCP 通信 | AF_INET | SOCK_STREAM | 0 (默认 TCP) |
UDP 通信 | AF_INET | SOCK_DGRAM | 0 (默认 UDP) |
本地进程通信 | AF_UNIX | SOCK_STREAM | 0 |
抓取原始包 | AF_PACKET | SOCK_RAW | htons(ETH_P_ALL) |
返回值
-
成功:返回套接字文件描述符(
sockfd
),用于后续操作(如bind
、connect
)。 -
失败:返回
-1
,并设置errno
(如EACCES
权限不足、EAFNOSUPPORT
不支持的协议族)。
完整示例(TCP 客户端)
c
复制
#include <sys/socket.h> #include <stdio.h> #include <unistd.h> int main() { int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { perror("socket creation failed"); return -1; } printf("Socket created successfully.\n"); close(sockfd); return 0; }
注意事项
-
权限要求:创建原始套接字(
SOCK_RAW
)需要CAP_NET_RAW
权限(通常需 root 用户)。 -
协议匹配:
domain
、type
和protocol
必须有效组合(如AF_INET
+SOCK_STREAM
只能配 TCP)。 -
资源释放:套接字使用后应调用
close()
关闭,避免文件描述符泄漏。
通过合理配置这三个参数,可以创建适应不同网络场景的套接字,为后续的 bind
、connect
、send
/recv
等操作奠定基础。