以linux4.0.1为蓝本,分析内核源码实现
用户层TCP
用户层的 TCP 编程模型大致如下,对于服务端,调用 listen 监听端口,之后接受客户端的请求,然后就可以收发数据了。结束时,关闭 socket。
// Server
socket(...,SOCK_STREAM,0);
bind(...,&server_address, ...);
listen(...);
accept(..., &client_address, ...);
recv(..., &clientaddr, ...);
close(...);
对于客户端,则调用 connect 连接服务端,之后便可以收发数据。最后关闭 socket。
socket(...,SOCK_STREAM,0);
connect();
send(...,&server_address,...);
那么根据我们的需求,我们着重照顾连接的建立、关闭和封包的收发过程。
探寻 tcp_prot,地图 get
一般游戏的主角手中,都会有一张万能的地图。为了搞定 TCP,我们自然也是需要一张地图的,要不连该去找那个函数看都不知道。很有幸,在tcp_ipv4.c中, tcp_prot定义了tcp的各个接口。
struct proto tcp_prot = {
.name = "TCP",
.owner = THIS_MODULE,
.close = tcp_close,
.connect = tcp_v4_connect,
.disconnect = tcp_disconnect,
.accept = inet_csk_accept,
.destroy = tcp_v4_destroy_sock,
.shutdown = tcp_shutdown,
.setsockopt = tcp_setsockopt,
.getsockopt = tcp_getsockopt,
.recvmsg = tcp_recvmsg,
.sendmsg = tcp_sendmsg,
.sendpage = tcp_sendpage,
.backlog_rcv = tcp_v4_do_rcv,
.get_port = inet_csk_get_port,
.twsk_prot = &tcp_timewait_sock_ops,
.rsk_prot = &tcp_request_sock_ops,
};
tcp_prot的类型为struct proto,是这个结构体是为了抽象各种不同的协议的差异性而存在的。类似面向对象中所说的接口 (Interface) 的概念。上面只保留了我们关心的部分
对着这张 ‘‘地图’’,就可以顺藤摸瓜,找出些路径了。