TCP 连接在内核中是如何管理的
基础概念题
1. TCP 连接在内核中是以什么数据结构管理的?请详细解释其组成
参考答案:
TCP 连接在内核中主要通过 套接字(Socket) 数据结构进行管理,核心包括:
核心组件详解:
- Socket 结构体:
struct sock {
struct sock_common __sk_common; // 连接四元组信息
socket_lock_t sk_lock; // 锁机制
struct sk_buff_head sk_receive_queue; // 接收队列
struct sk_buff_head sk_write_queue; // 发送队列
int sk_state; // TCP 状态
// ... 更多字段
};
- TCP Control Block (TCB):
struct tcp_sock {
struct inet_connection_sock inet_conn;
u32 snd_nxt; // 下一个要发送的序列号
u32 snd_una; // 未确认的最小序列号
u32 rcv_nxt; // 期望接收的下一个序列号
u32 rcv_wnd; // 接收窗口大小
// ... 拥塞控制、重传等字段
};
面试追问:Go 语言中的 net.Conn 是如何与内核 socket 关联的?
2. 请解释 TCP 连接的四元组是什么,内核如何基于四元组管理连接?
参考答案:
四元组组成:
- 源 IP 地址 (Source IP)
- 源端口号 (Source Port)
- 目标 IP 地址 (Destination IP)
- 目标端口号 (Destination Port)
内核管理机制:
哈希表查找过程:
// 简化的内核查找逻辑
struct sock *tcp_lookup_established(struct net *net,
__be32 saddr, __be16 sport,
__be32 daddr, __be16 dport) {
unsigned int hash = tcp_hashfn(saddr, sport, daddr, dport);
struct sock *sk;
// 在已建立连接的哈希表中查找
sk_for_each(sk, &tcp_hashinfo.ehash[hash]) {
if (sk->sk_daddr == saddr && sk->sk_sport == sport &&
sk->sk_rcv_saddr == daddr && sk->sk_dport == dport) {
return sk;
}
}
return NULL;
}
Go 语言中的应用:
func main() {
// 客户端四元组:本机IP:随机端口 -> 服务器IP:8080
conn, err := net.Dial("tcp", "192.168.1.100:8080")
if err != nil {
log.Fatal(err)
}
// 打印本地和远程地址
fmt.Printf("Local: %s, Remote: %s\n",
conn.LocalAddr(), conn.RemoteAddr())
}