深入解析 Python Socket 创建:socket.socket(socket.AF_INET, socket.SOCK_STREAM)
从网络协议到代码实现的全面解读
核心代码架构图
graph TD
A[socket.socket()] --> B[地址族 Address Family]
A --> C[套接字类型 Socket Type]
A --> D[协议 Protocol]
B --> B1["socket.AF_INET → IPv4"]
B --> B2["socket.AF_INET6 → IPv6"]
B --> B3["socket.AF_UNIX → Unix域"]
C --> C1["socket.SOCK_STREAM → TCP"]
C --> C2["socket.SOCK_DGRAM → UDP"]
C --> C3["socket.SOCK_RAW → 原始套接字"]
D --> D1["默认值 0 → 自动选择"]
D --> D2["IPPROTO_TCP → TCP协议"]
D --> D3["IPPROTO_UDP → UDP协议"]
三层核心参数详解
1. 地址族(Address Family)
作用:确定网络协议栈类型
import socket
# 主要地址族常量
print("IPv4 地址族:", socket.AF_INET) # 输出: 2 (通常值)
print("IPv6 地址族:", socket.AF_INET6) # 输出: 10 (通常值)
print("Unix域套接字:", socket.AF_UNIX) # 输出: 1 (通常值)
| 地址族 | 协议版本 | 地址格式 | 典型应用场景 |
|---|---|---|---|
AF_INET |
IPv4 | (host, port) |
标准互联网通信 |
AF_INET6 |
IPv6 | (host, port, flowinfo, scopeid) |
现代网络应用 |
AF_UNIX |
本地通信 | 文件路径字符串 | 进程间通信(IPC) |
💡 为什么使用常量:
避免硬编码(如直接写2),提高代码可读性和跨平台兼容性
2. 套接字类型(Socket Type)
作用:确定数据传输方式
# 主要套接字类型
print("TCP流套接字:", socket.SOCK_STREAM) # 输出: 1
print("UDP数据报:", socket.SOCK_DGRAM) # 输出: 2
print("原始套接字:", socket.SOCK_RAW) # 输出: 3
| 套接字类型 | 传输特性 | 可靠性 | 连接导向 | 适用协议 |
|---|---|---|---|---|
SOCK_STREAM |
字节流 | 高 | 是 | TCP |
SOCK_DGRAM |
数据报文 | 低 | 否 | UDP |
SOCK_RAW |
原始网络层访问 | - | 否 | ICMP等 |
3. 协议(Protocol)
作用:精确指定传输协议(通常可省略)
# 常见协议常量
print("TCP协议:", socket.IPPROTO_TCP) # 输出: 6
print("UDP协议:", socket.IPPROTO_UDP) # 输出: 17
底层实现解析
# Python socket 模块底层C代码简化版
static PyObject * socket_socket(PyObject *self, PyObject *args) {
int family = AF_INET; // 默认地址族
int type = SOCK_STREAM; // 默认套接字类型
int proto = 0; // 默认协议
// 解析Python传入的参数
if (!PyArg_ParseTuple(args, "|iii", &family, &type, &proto))
return NULL;
// 创建底层套接字描述符
int sockfd = socket(family, type, proto);
if (sockfd == -1) {
PyErr_SetFromErrno(PyExc_OSError); // 操作系统错误
return NULL;
}
// 封装为Python对象
return (PyObject*)new_sockobject(sockfd, family, type, proto);
}
关键步骤:
- 解析Python传入的常量值
- 调用操作系统
socket()系统调用 - 创建套接字文件描述符
- 封装为Python对象返回


1694

被折叠的 条评论
为什么被折叠?



